有些信息在存储时,并不须要占用一个完整的字节,而只须要占用一个或几个二进制位。数据结构
例如: 存放一个开关量时,只有0和1二种状态,只保存一位二进制位便可。为了节省存储空间,C语言提供了数据结构:位域。测试
位域是把字节中的二进制位划分为几个不一样的区域,并说明每一个区域的位数。每一个区域有个域名,容许在程序中按域名spa
进行操做。这样就能够把几个不一样的对象用一个字节的二进制位域来表示。code
位域的定义对象
位域定义与结构体定义相仿,形式为:blog
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字节