概念引入:
C语言中的位域的使用
C/C++位域
位域使用:
位域成员不能单独被取sizeof值(编译报错),我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其它类型类型的存在。使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
和结构体一样,位结构体也是按照成员的最大长度字节来对齐分配空间的。
实验范例:
例1:对位域的赋值不能超过其允许的范围,整个结构体的总大小为最宽基本类型成员大小的整数倍。如下为int(即4字节)的整数倍。
#include<iostream> using namespace std; struct bs { int a:23;//如果24则sizeof(bs)=8; int b:3;//限定了b的范围只能是000-111。 int c:6; }; int main() { struct bs b; b.a=64; b.b=3;//011,第一位表示正负号,0正1负 ,0后面的11表示3。 b.c=10; cout<<sizeof(b)<<endl; cout<<b.a<<" "<<b.b<<" "<<b.c<<endl;//sizeof: int 4、unsigned int 4、short int 2、unsigned short 2、long int 4、unsigned long 4、float 4、double 8、long double 12、char 1 、unsigned char 1 getchar(); }
如果把int a:23->24,b.b=3-->4。则结果如下:
#include<iostream> using namespace std; struct bs { int a:24;//如果24则sizeof(bs)=8; int b:3;//限定了b的范围只能是000-111。 int c:6; }; int main() { struct bs b; b.a=64; b.b=4;//100,第一位表示正负号,0正1负 . b.c=10; cout<<sizeof(b)<<endl; cout<<b.a<<" "<<b.b<<" "<<b.c<<endl;//sizeof: int 4、unsigned int 4、short int 2、unsigned short 2、long int 4、unsigned long 4、float 4、double 8、long double 12、char 1 、unsigned char 1 getchar(); }
如果b.b=13,即1101,超过了000-111的范围。数据就会被截断。cout<<b.b<<endl的结果-3。说明留下了101。前面多出的部分被截断。
如果b.b=9,即1001,超过了000-111的范围。数据就会被截断。cout<<b.b<<endl的结果1。说明留下了001。前面多出的部分被截断。
例2:相邻的位域字段的类型不同
#include<iostream> using namespace std; struct test { char a:1; int b:3; char c:2; }; int main() { test t1; cout<< sizeof(t1)<<endl; getchar(); return 0; }在devc++下,结果为4。压缩。
在vc6.0下,结果为12。不压缩。