C语言位域浅析
位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。
位段的定义格式为:
type [var]: digits
其中:
type只能为int,unsigned int,signed int,char, unsigned char 五种类型之一,digits表示该位段所占的二进制位数
位段长度digits不能超过类型type对应的数据类型占用的大小,如若type为char,则digits不能超过8,为int则digits不能超过32
位段名称var是可选参数,可以省略
一、位域的定义
位域定义与结构体定义相仿,其形式为:
struct 位域结构名
{
位域列表
};
其中位域列表的形式为: type [var]: digits
例如:
1 struct data{ 2 3 int a : 32; //位段a,占32位 4 5 char b : 5; //位段b,占5位 6 7 char c : 2; //位段c,占2位,和b存储在同一个字节 8 9 unsigned char : 6; //无名位段,占6位 10 11 };
注:位域可以无位域名,这时它只用来作填充或调整位置,无名的位域不能被访问
二、位段的使用
位域的使用和结构成员的使用相同,其一般形式为:位域变量名·位段名,也可定义一个指向位域的指针p,然后p->位段名使用,使用时需要注意:
①不能对位段进行取地址操作
②若位段占的二进制位数为0,则这个位段必须是无名位段,下一个位段从下一个位段存储单元开始存放
③若位段出现在表达式中,则会自动进行整型升级,自动转换为int型或者unsigned int
④对位段赋值时,最好不要超过位段所能表示的最大范围,否则可能会造成意想不到的结果
三、位段在内存中的存储模式
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,经实验VC采取不压缩方式,即即使前一个字段有空余位足够容纳后一个字段,后一个字段也当前一个字段 没有空余位,从前一个字段类型大小之后的新字节开始存储;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。:
测试程序如下,环境vs3013,cfree 5.0
#include <stdio.h> #include <stdlib.h> struct data{ int a : 20; //位段a,占20位 char b : 3; //位段b,占3位,不会和a压缩存储 char : 0; //无名位段 unsigned char c : 5; //位段c,占5位 }; int main() { data test; data *ptest; ptest = &test; //两种方式访问位段 test.a = 20; ptest->b = 5; //vc不压缩存储,占用8个字节,为其最宽基本类型成员大小的整数倍 printf("sizeof(data): %d\n",sizeof(data)); //test.b在输出时自动转化为整型,5(101)高位为1,扩展时高位连续补1,值为-3 printf("test.a = %d\t test.b = %d\n",test.a, ptest->b); system("pause"); return 0; }
运行结果为:
sizeof(data): 8
test.a = 20 test.b = -3
参考:
http://www.cnblogs.com/dolphin0520/archive/2011/10/14/2212590.html