一、位段结构
struct node
{
unsigned int a:4; //位段a,占4位
unsigned int :0; //无名位段,占0位
unsigned int b:4; //位段b,占4位
int c:32; //位段c,占32位
int :6; //无名位段,占6位
char g;
};
二、位段的使用
使用位段需注意一下几点:
1)位段的类型只能是int,unsigned int,signed int三种类型,不能是char型或者浮点型;
2)位段占的二进制位数不能超过该基本类型所能表示的最大位数,比如在VC中int是占4个字节,那么最多只能是32位;
3)无名位段不能被访问,但是会占据空间;
4)不能对位段进行取地址操作;
5)若位段占的二进制位数为0,则这个位段必须是无名位段,下一个位段从下一个位段存储单元开始存放;
6)若位段出现在表达式中,则会自动进行整型升级,自动转换为int型或者unsigned int。
7)对位段赋值时,最好不要超过位段所能表示的最大范围,否则可能会造成意想不到的结果。
8)位段不能出现数组的形式。
三、位段内存中存储方式
对于位段结构,编译器会自动进行存储空间的优化,主要有这几条原则:
1)如果一个位段存储单元能够存储得下位段结构中的所有成员,那么位段结构中的所有成员只能放在一个位段存储单元中,不能放在两个位段存储单元中;如果一个位段存储单元不能容纳下位段结构中的所有成员,那么从剩余的位段从下一个位段存储单元开始存放。
2)如果一个位段结构中只有一个占有0位的无名位段,则只占1或0字节的空间(C语言中是占0字节,而C++中占1字节);否则其他任何情况下,一个位段结构所占的空间至少是一个位段存储单元的大小;
四、位段使用实例
eg 1:
/*测试位段*/
#include<stdio.h>
typedef struct node
{
unsigned int a:1; //存在一个非0位的位段,则至少占4Byte
}S;
typedef struct node1 //在C++中占1字节的空间 ,在C中占0字节
{
unsigned int :0;
}S1;
typedef struct node2
{
unsigned int a:1;
unsigned int :0; //下一个位段放在一个新的位段存储单元 ,所以占4+4=8Byte
unsigned c:32;
}S2;
typedef struct node3
{
unsigned int a:4;
unsigned int :0;
int :6; //这个位段放在一个新的位段存储单元
unsigned c:32; //由于6+32>32,所位段c也放在一个新的位段存储单元,所以占4+4+4=12Byte
}S3;
typedef struct node4
{
int a:1;
char b; //在一个位段存储单元中能够存下所有的成员,所以占4Byte
int c:1;
unsigned int d:2;
unsigned int e:2;
}S4;
int main(int argc, char *argv[])
{
S4 s4;
s4.a=1;
s4.c=1;
s4.d=2;
s4.e=3;
printf("%d %d %d %d\n",s4.a,s4.c,s4.d,s4.e);
printf("%d %d %d %d %d\n",sizeof(S),sizeof(S1),sizeof(S2),sizeof(S3),sizeof(S4));
return 0;
}
OUTPUT:
注意仔细思考:为什么输出结果为 -1 -1 2 3 ????
想想上一篇博客提到的符号位扩展的问题。(若位段出现在表达式中,会自动进行整型升级)
由于c只占用1位,没有数据位,直接进行符号位扩展,高位添1,
(1111 1111 1111 1111 1111 1111 1111 1111)补 -》 (ox FF FF FF FF FF FF FF FF)补 -》 (ox 80 00 00 00 00 00 00 01)原 -》 (-1)真值
eg 2:
struct test{
int a:1;
int b:1;
int c:1;
}
void main()
{
test t;
t.a = 1;
t.b = 0;
t.c = -1;
printf("%d,%d,%d,%d",t.a,t.b,t.c,sizeof(t));
}
OUTPUT:
-1,0,-1,4
参考链接:
http://www.cnblogs.com/dolphin0520/archive/2011/10/14/2212590.html