位域(位段)

  有些信息在存储时,并不需要占用一个完整的字节,而只需要占用一个或几个二进制位。

例如: 存放一个开关量时,只有0和1二种状态,只保存一位二进制位即可。为了节省存储空间,C语言提供了数据结构:位域。

  位域是把字节中的二进制位划分为几个不同的区域,并说明每个区域的位数。每个区域有个域名,允许在程序中按域名

进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

位域的定义

  位域定义与结构体定义相仿,形式为:

struct 位域结构名

{

  类型名  位域名: 位域长度,如 int a 8;  //位域长度不能大于8(即一个字节)

  ......

};

 

注意:

  一个位域必须存储在一个字节中,当有二个连续的位域,在一个字节中存放第一个位域后剩下的空间不足以存放第二个

位域,则第二个位域将存放在下一个字节单元中,前一个字节多余的位补0。(因为一个位域必须存储在一个字节,所以位域长度最大为8)

 

 
1 struct wy
2 {
3   unsigned int a : 4; //第一个字节前4位存放该位域
4   unsigned int b : 5; //第一个字节剩下的4位不足以存放b,位域b从下一个字节开始
5 }WY;
6 sizeof(WY) == 4;位域存储的类型是int占用4个字节,根据内存对齐规则不足4字节也占用4字节。对齐规则可以往下看

 

空域:

  不管当前字节单元剩下的位数是否足以存放下一个位域,使用空域后,下一个位域都存放到下一个类型单元,比如int就存放到下个int单元

 
1 struct wyn
2 {
3   unsigned int a : 4; //第一个字节前4位存放该位域
4   unsigned int :0;
5   unsigned int b : 2; //空域后的位域从下个单元开始
6 }WYN;
7 sizeof(WYN) == 8; 因为存储的类型是int型,空域后,从下个int开始
 
 

wyn nn;  nn.a = 6; //给a赋值为6其实是把a占用的4位赋值为 0110

 当一个位域无位域名时,它只是用来作为填充或调整位置,不能被使用(比如 int :3 仅仅是用来占3位二进制位,但这3位没法在程序里使用)。

位域内存对齐规则

1 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof(类型)大小,则后面的字段紧邻前一个字段存储。

2 如果相邻位域字段的类型相同,且其位宽之和大于类型的sizeof(类型)大小,则后面的字段从新的存储单元开始,其偏移量为sizeof(类型)大小的整数倍

3 如果相邻位域字段的类型不同,则各编译器的具体实现有差异,需要在编译器上测试

 

 
1 struct wyn
2 {
3   unsigned int i : 8;
4   unsigned int j : 4;
5   unsigned int a : 3;
6   double b;
7 }WYN; 8 sizeof(WYN) == 16;
i,j,a共占用2个字节,根据规则1,紧邻的int型i,j,a共占用4字节。
b位double型,占用8字节,根据对齐规则,b的内存地址必须是8的整数倍,所以在i,j,a后会填充4个字节,再存储b。
 
 
 
1 struct wyn2
2 {
3   unsigned int i : 8;
4   unsigned int j : 4;
5   double b; 
6   unsigned int a : 3;
7 }WYN2; 8 sizeof(WYN2) == 24;
同上面WYN一样,根据规则1,2:i,j,b占用16字节
位域a占用3位,类型是int应该占用4字节,但是整个结构体大小应该按照最大的类型double对齐,必须是8的整数倍。所以占用24字节
 
 
 

 

posted on 2019-05-25 15:45  锋邢天下  阅读(601)  评论(0编辑  收藏  举报

导航