位段
C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。位段是基于结构体来实现的。
![](https://i-blog.csdnimg.cn/blog_migrate/e8dc7a81da04916d746a6289f2f04640.png)
位:代表二进制位
位段的成员变量必须是 int , unsigned int , signed int;
位段的成员后面有一个冒号和数字。
![](https://i-blog.csdnimg.cn/blog_migrate/f300267acad1109564e0d5f1017ea0d6.png)
剩下15个有没有用看编译器,位段的设计是不确定的
![](https://i-blog.csdnimg.cn/blog_migrate/89099075736801f4160d3da7e3b0ffec.png)
开辟内存的空间
![](https://i-blog.csdnimg.cn/blog_migrate/56b7eef86b06c1ce8cc90e89971dc9e1.png)
结果
![](https://i-blog.csdnimg.cn/blog_migrate/1c4c41011cc2f64d31e89f9571605026.png)
位段不存在对齐,其实就是用空间来牺牲空间
位段的跨平台问题
1.位段的成员可以是:int ,unsigned int ,signed int ,或者,char (属于整型家族)类型!
2.位段的空间是按照需要以4个字节(int )或者1个字节(char)的方式开辟的
3.位段涉及很多不确定的因素,位段是不跨平台的,注意课移植的程序应该避免使用位段!
总结
跟结构体相比,位段可以达到相同的效果,但是可以很好的节省空间,但是有跨平台的问题存在!!
刷题
下面代码的结果是( )
int main()
{
unsigned char puc[4];
struct tagPIM
{
unsigned char ucPim1;
unsigned char ucData0 : 1;
unsigned char ucData1 : 2;
unsigned char ucData2 : 3;
}*pstPimData;
pstPimData = (struct tagPIM*)puc;
memset(puc,0,4);
pstPimData->ucPim1 = 2;
pstPimData->ucData0 = 3;
pstPimData->ucData1 = 4;
pstPimData->ucData2 = 5;
printf("%02x %02x %02x %02x\n",puc[0], puc[1], puc[2], puc[3]);
return 0;
}
A.02 03 04 05
B.02 29 00 00
C.02 25 00 00
D.02 29 04 00
puc是一个char数组,每次跳转一个字节,结构体不是,它只有第一个元素单独享用一字节,其他三个元素一起共用一字节,所以puc被结构体填充后,本身只有两个字节会被写入,后两个字节肯定是0,至此AD排除,然后第一个字节是2就是2了,第二个字节比较麻烦,首先ucData0给了3其实是越界了,1位的数字只能是0或1,所以11截断后只有1,同理ucData1给的4也是越界的,100截断后是00,只有5的101是正常的。填充序列是类似小端的低地址在低位,所以排列顺序是00 101 00 1。也就是0010 1001,即0x29,故选B。
![](https://i-blog.csdnimg.cn/blog_migrate/46445479e568c3c7d01e65fe28942115.png)
计算机进制转换器: