类和结构可包含比整型类型占用更少存储空间的成员。这些成员被指定为位域。位域成员声明符规范的语法如下:
语法
declarator : constant-expression
下面的示例声明包含位域的结构:
// bit_fields1.cpp // compile with: /LD struct Date { unsigned short nWeekDay : 3; // 0..7 (3 bits) unsigned short nMonthDay : 6; // 0..31 (6 bits) unsigned short nMonth : 5; // 0..12 (5 bits) unsigned short nYear : 8; // 0..100 (8 bits) };
Date 类型的对象的概念上的内存布局如下图所示。
请注意,nYear 的长度为 8 位,并且会溢出声明类型 unsigned short 的字边界。因此,它始于新 unsigned short 的开头。并不必使所有位域均适合基础类型的对象;根据声明中请求的位数来分配新的存储单元,因此该结构体大小为4个字节。声明为位域的数据从低位到高位进行排序,如上图所示。
如果结构的声明包含长度为 0 的未命名字段(如以下示例所示),
// bit_fields2.cpp // compile with: /LD struct Date { unsigned nWeekDay : 3; // 0..7 (3 bits) unsigned nMonthDay : 6; // 0..31 (6 bits) unsigned : 0; // Force alignment to next boundary. unsigned nMonth : 5; // 0..12 (5 bits) unsigned nYear : 8; // 0..100 (8 bits) };
则内存布局如下图中所示。
位域的基础类型必须是整型类型,如基本类型中所述。
总结如下
使用位域的主要目的是压缩存储,其大致规则为:
- 1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
- 2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
- 3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
- 4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
- 5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
案例如下:
typedef struct AA{
unsigned char b1:5;
unsigned char b2:5;
unsigned char b3:5;
unsigned char b4:5;
unsigned char b5:5;
}AA;/*sizeof(AA) = 5*/
typedef struct BB {
unsigned int b1:5;
unsigned int b2:5;
unsigned int b3:5;
unsigned int b4:5;
unsigned int b5:5;
}BB;/*sizeof(BB) = 4*/
typedef struct CC {
int b1:1;
int :2;//无影响
int b3:3;
int b4:2;
int b5:3;
short b6:4;
int b7:1;
}CC; /*sizeof(CC) = 12*/