首先位段的定义为:
struct 位段结构name
{
TypeDef 位域名 : num; //num标志占用的位数
};
例如:
struct Date1
{
int a : 1;
int b : 5;
}date1; //这里a表示位域名 1表示占用一个bit
那数据如何在内存中存储呢?
在网上找了个存储原则:
如果结构体中含有位域(bit-field),那么VC中准则是:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;
系统会先为结构体成员按照对齐方式分配空间和填塞(padding),然后对变量进行位域操作。
再举个例子分析一下:
struct Date1
{
unsigned int a : 5;
unsigned int b : 2;
}date1;
int main(void)
{
date1.a = 1;
date1.b = 2;
return 0;
}
那莫在内存中存储为(当然默认int占4个Byte)
0000 0000 0000 0000 0000 0000 0100 0001 红色的位域名为a 绿色为b
那么printf 出来结果date1.a应该为1 .b应该为2
不过上面的例子稍微改一下,则结果将发生变化
struct Date1
{
int a : 5;
int b : 2;
}date1;
int main(void)
{
date1.a = 1;
date1.b = 2;
return 0;
}
虽然在内存存储没有发生变化 但是a域读取出来后 系统将对其进行符号扩展 那么00001由于符号位为0 扩展为0000 0000 0000 0000 0000 0000 0000 0001
对于b择优 1111 1111 1111 1111 1111 1111 1111 1110 那么打印出来将是-2
另外还有一点需要注意:
那就是位段里面是不能对位域取地址的 否则出错
struct Date1
{
int a : 1;
int : 0; //那无论本位段是否还有空间,下一个变量都将在下一个位段存储
int b : 5;
}date1;
或者
struct Date1
{
int a : 1;
int : 3; //本位域将仅仅是占一个位置,并不可以使用
int b : 5;
}date1;