C语言中的位域

struct 位域结构名

{

   位域类型 位域名:占用位的长度;(位域列表)

};

1、使用位域可能不如使用位运算符的执行速度快,但是位域使程序更容易阅读。


2、如果某个作用域中定义了位域结构,则在该作用域中就不能使用typedef或#define来定义与位域结构名相同的类型名。


3、在之前的标准中,位域类型必须是int、unsigned int或signed int。使用int会引起二义性,因为一些编译器将位域的最高位作为符号位,而其他一些编译器则不会;另一方面,如果使用signed int类型若使用到了正负,也会存在问题。故建议使用unsigned int类型。

   在C99新标准中,编译器还允许使用_Bool类型,不过一些编译器在具体实现时,额外支持了char、unsigned char、signed char、enum类型。


4、每个位域结构都会定义自己的作用域,所以花括号内部定义的位域名可以和其他作用域中的变量同名,而内部不可以同名。

   α、C语言允许省略位域的名字。


5、占用位的长度可以根据需要进行配置,但是不能超过位于类型所占的总位数。

   β、在省略位域名时可以为零。


6、C语言不允许将&运算符用于位域,所以,向scanf这样的函数无法直接向位域中存储数据。可以通过使用一个临时变量的方法间接存储。


7、位域内存分布

   7.1、当编译器处理位域这种结构的声明时,会将位域逐个放入存储单元,位域之间没有间隙,直到剩下的空间不够用来放下一个位域了。这时,一些编译器会跳到下一个存储单元的开始,另一些则会将位域拆开跨存储单元存放。位域的存放循序(从左到右还是从右到左)也由实现决定。

   7.2、上面第4点提到的省略位域名,经常用来作为字段间的“填充”,以保证其它位域存储在适当的位置。

   7.3(γ)、另一个用来控制位域存储的技巧是指定未命名的字段长度为0。这是给编译器一个信号,告诉编译器将下一个位域在一个存储单元的起始位置对齐。

   7.4、

相邻位域字段的类型 位宽之和与类型比较 结果
相同 小于 紧邻的存储在该类型大小的空间中(压缩)
相同 大于 大于的部分从下一个该类型大小的空间中开始存储
不同   依编译器而定,(GCC会压缩,VS、VC不会)

 

   7.5、只有相邻的位域才能被压缩,若位域列表之间有一个非位域则会被分成两部分,两部分单独考虑。

    7.6、因为存在数据内存对齐问题,所以整个位域结构体的总大小为最宽基本类型成员大小的整数倍,这一点与结构体类型是一致的。


8、若位段出现在表达式中,则会自动进行整型提升,转换为int或unsigned int。


总结:位域使用的最佳策略是:

1、位域的类型要使用合适的且占用内存最小的无符号类型。

2、整个位域列表尽量使用相同的类型(数据对齐问题会引起不必要的内存消耗)。

2、不要在位域列表中间插入非位域。

3、合理的布局位域列表的顺序。

展开阅读全文

没有更多推荐了,返回首页