C语言中提供了位字段(bit field)的概念,也称为位域。在C中大都是在结构体内使用位域的方法,这种方法可以节约在不需要那么多位的情况下节约内存空间,并且处理起来也很简单。它的声明形式如下:
struct
{
unsigned char bitfield1 : 2;
unsigned char bitfield2 : 4;
unsigned char : 2;
unsigned char bitfield3 : 3;
unsigned char : 0;
.....
variable type name : n;
}
这种类型的声明方式在很多ARM内核的MCU头文件中都使用这种方式,因为MCU的控制寄存器用位域的方式处理更加快捷与直观。
在位字段的使用过程中有几点需要注意:
1.关于位变量的内存占用大小与内存分配。位变量类型只能声明为整形,如char ,int。比如上面的例子而言,field1和field2是共同占用一个unsigned char类型的空间大小的,并不是占用两个unsigned char空间大小,如果连续的几个位变量所占用的空间大小超出了所定义类型的大小编译器会自动的将超过的位字段分配到下一个连续的空间中,但不允许跨界占用,如上面的例子field1和field2会放在同一个unsigned char空间内,但field3占有3个bit,编译器不会把其中的2bit放在和field1,field2同一个字节空间内,而是会直接放到下一个字节空间中,所以在上一个字节空间内也就存在了2bit的空洞,就浪费了。这种情况下是没有方法直接避免浪费的这2个bit的,除非你在其中放入刚好只有2个bit的位变量,不过也可以人为的放入没有位变量名的位变量直接将其跳过,如上。还有就是声明一个0宽度的位变量会直接强制编译器将接下的位变量放入下一个字节中。不同的编译器中位变量在空间的排列也不同,比如MicroSoft Visual C++6.0对位字段在空间上的排列在从右向左,即首先放在最低位。
2.关于位变量的赋值问题,位变量是声明在结构体内部的,所以对于它的赋值方式基本上和结构体变量的赋值是相同的,但要注意的是赋值的范围是根据此位变量的位数来定的,比如,field1最大只能赋3,因为超过3了,也就超出的field1的最大位数了。位变量主要用于那此选择情况较少的,比如是与否等等,因为这样的话你就没必要去专门声明一个变量去表示了,大大的节约的内存占有率,同样也直观。在补充一点关于C中字节对齐的原则:
1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.
644398774_263592779 2013-10-12 01:01
huhaomcu_856934054 2013-9-29 09:01
用户1602177 2013-9-17 16:10
allen_zhan_752827529 2013-9-15 21:08
用户516996 2013-1-5 10:23