在C语言的结构体中,可以使用一个字节的某几位来定义一个成员,成为位域,如
struct A
{
int a:4;
int b:5;
int c:7;
};
表示该结构体有三个成员,成员a占一个字节的4位,成员b占5位,成员c占7位。
关于位域在内存中的存储,有如下几个特性:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止。
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍。
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式。
4) 如果位域字段之间穿插着非位域字段,则不进行压缩。
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
示例如下:
#include <stdio.h>
struct A
{
int a:4;
int b:5;
int c:7;
};
struct B
{
short a:4;
short b:5;
short c:7;
};
struct C
{
char a:4;
char b:5;
char c:7;
};
struct D
{
char c:7;
int a:4;
short b:5;
};
int main()
{
printf("size: %d\n", sizeof(struct A)); //输出为4.成员都为整型,且位宽之和(4+5+7)小于类型大小(sizeof(int) = 4),因此成员被合并存储。又因为“整个结构体的总大小为最宽基本类型成员大小的整数倍”,因此大小为4
printf("size: %d\n", sizeof(struct B)); //输出为2.成员为short型,且位宽之和等于类型大小,因此成员被合并存储,因此结构体大小正好为一个short型大小
printf("size: %d\n", sizeof(struct C)); //输出为3.成员都为char型,但位宽之和大于类型大小,因此成员没有被合并存储,因此结构体大小为3
printf("size: %d\n", sizeof(struct D)); //输出为4.成员类型不同,不进行合并,以此存储,因此大小为4
struct D d;
memset((void *)&d, 0, sizeof(d));
d.a = 1;
d.b = 1;
d.c = 1;
printf("value: %#x\n", *(int *)&d); //输出为0x881.表明成员按照字节以此存储
}
说明:以上代码都是在gcc 4.3下测试,其他编译器没有测试