有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
例如:
struct p { int a:8; int b:2; int c:6; }data;在内存中即:
高位 0000 |0000 00|00|0000 0000| 低位
c b a
这里有几点需要说明:
1.位域的大小不能超过所定义的数据类型,比如int是32位,若定义int a:33则编译器会报错error C2034:“p::a”:位域类型对位数太小
2.如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
3.如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
4.如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;
下面举一些例子来佐证:
struct p
{
char a:7;
char b:2;
char c:6;
}data;
高位 0000 |0000 00|00 0|000 0000| 低位 (a占去了8bit中的7bit,剩下的1bit放不下b,所以b放入新的单元)
c b a
struct p{ short a:7; short b:2; short c:6; }data;
此时情况则不同,因为short型有16位,abc都可以放下
高位 0000 |0000 00|00 |0000 0000| 低位
c b a
struct p{ short a:7; char b:2; char c:6; }data;在VC中,即使b可以放在a的后面,但它们的数据类型不一样,故b需要放入新单元
高位0000 00|00| 0000 0000 0|000 0000| 低位
c b a