文章详情页 您现在的位置是:网站首页>文章详情
C语言结构体中的位字段
WBK 发表于:2019年5月8日 17:10 分类:【嵌入式软件】 4339次阅读
C语言结构体中有一个用起来很方便的东西,叫位字段,可以定义每一个变量的位的大小。
一般在嵌入式软件设计中,很多数据命令的寄存器有固定的位数,可以用位字段来解析和赋值。
C Primer Plus书中的位字段内容如下:
位字段是一个signed int或unsigned int类型变量中的一组相邻的位(C99和C11新增了_Bool类型的位字段)。位字段通过一个结构声明来建立,该结构声明为每个字段提供标签,并确定该字段的宽度。例如,下面的声明建立了一个4个1位的字段:
struct { unsigned int autfd : 1; unsigned int bldfc : 1; unsigned int undln : 1; unsigned int itals : 1; }prnt;
根据该声明,prnt包含4个1位的字段。现在,可以通过普通的结构成员运算符(.)单独给这些字段赋值:
prnt.itals = 0; prnt.undln = 1;
由于每个字段恰好为1位,所以只能为其赋值1或0。变量prnt被储存在int大小的内存单元中,但是在本例中只使用了其中的4位。
带有位字段的结构提供一种记录设置的方便途径。许多设置(如,字体的粗体或斜体)就是简单的二选一。例如,开或关、真或假。如果只需要使用 1 位,就不需要使用整个变量。内含位字段的结构允许在一个存储单元中储存多个设置。
有时,某些设置也有多个选择,因此需要多位来表示。这没问题,字段不限制 1 位大小。可以使用如下的代码:
struct { unsigned int code1 : 2; unsigned int code2 : 2; unsigned int code3 : 8; } prcode;
以上代码创建了两个2位的字段和一个8位的字段。可以这样赋值:
prcode.code1 = 0; prcode.code2 = 3; prcode.code3 = 102;
但是,要确保所赋的值不超出字段可容纳的范围。
如果声明的总位数超过了一个unsigned int类型的大小会怎样?会用到下一个unsigned int类型的存储位置。一个字段不允许跨越两个unsigned int之间的边界。编译器会自动移动跨界的字段,保持unsigned int的边界对齐。一旦发生这种情况,第1个unsigned int中会留下一个未命名的“洞”。
可以用未命名的字段宽度“填充”未命名的“洞”。使用一个宽度为0的未命名字段迫使下一个字段与下一个整数对齐:
struct { unsigned int field1 : 1 ; unsigned int : 2 ; unsigned int field2 : 1 ; unsigned int : 0 ; unsigned int field3 : 1 ; }stuff;
这里,在stuff.field1和stuff.field2之间,有一个2位的空隙;stuff.field3将储存在下一个unsigned int中。
字段储存在一个int中的顺序取决于机器。在有些机器上,存储的顺序是从左往右,而在另一些机器上,是从右往左。另外,不同的机器中两个字段边界的位置也有区别。由于这些原因,位字段通常都不容易移植。尽管如此,有些情况却要用到这种不可移植的特性。例如,以特定硬件设备所用的形式储存数据。
在实际的使用中举例如下:
比如说Spi的数据解析,可以用到 共用体 和 位字段 。
比如说Spi的数据诊断返回值如下:
那么可以如下定义:
typedef union { uint32 DiagData; struct { uint32 R_W : 1 ; uint32 MSG_ID : 5 ; uint32 S2G_0 : 1 ; uint32 S2G_TST0 : 1 ; uint32 S2B_0 : 1 ; uint32 S2B_TST0 : 1 ; uint32 OL_OFF0 : 1 ; uint32 OL_ON0 : 1 ; uint32 S2G_1 : 1 ; uint32 S2G_TST1 : 1 ; uint32 S2B_1 : 1 ; uint32 S2B_TST1 : 1 ; uint32 OL_OFF1 : 1 ; uint32 OL_ON1 : 1 ; uint32 S2G_2 : 1 ; uint32 S2G_TST2 : 1 ; uint32 S2B_2 : 1 ; uint32 S2B_TST2 : 1 ; uint32 OL_OFF2 : 1 ; uint32 OL_ON2 : 1 ; uint32 S2G_3 : 1 ; uint32 S2G_TST3 : 1 ; uint32 S2B_3 : 1 ; uint32 S2B_TST3 : 1 ; uint32 OL_OFF3 : 1 ; uint32 OL_ON3 : 1 ; uint32 ENL : 1 ; uint32 RBL : 1 ; }DataAnalysis; }FaultDiagnostic;
将Spi接收的反馈数据赋值给
FaultDiagnostic.DiagData
就可以很方便的进行解析数据。
此定义用于芯片采用大端存储的方式,如果芯片采用的是小段存储,那么顺序需要倒置。
版权声明 本文属于本站 原创作品,文章版权归本站及作者所有,请尊重作者的创作成果,转载、引用自觉附上本文永久地址: http://blog.lujianxin.com/x/art/ak7d80qr8ciy
上一篇:C语言中的联合体Union
下一篇:敏捷开发
文章评论区
作者名片
- 作者昵称:WBK
- 原创文章:3篇
- 转载文章:1篇
- 加入本站:2043天
站长推荐
友情链接
站点信息
- 运行天数:2047天
- 累计访问:164169人次
- 今日访问:0人次
- 原创文章:69篇
- 转载文章:4篇
- 微信公众号:第一时间获取更新信息