深度C理解位域
深度C 理解位域(fylxaut 著) 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态,用一位二进位即可。为了节省存储空间,并
深度C 理解位域(fylxaut 著) 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态,用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为: struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
例如:
struct bs
{
int a:8;
int b:2;
int c:6;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////
struct foo1 {
int a : 1;
int : 2;/空域
short c : 1;

};
在foo 结构体的定义中,成员a 虽然类型为int ,但是它仅仅占据着4个字节中的一个bit 的空间;类似b 占据2个bit 空间,但是b 到底是占据第一个int 的2个bit 空间呢还是第二个int 的2个bit 空间呢?这里实际上也涉及到如何对齐带有' 位域' 的结构体这样一个问题。我们来分析一下。
struct foo2 {
char a : 2;
,char b : 3;
char c : 1;

};
struct foo3 {
char a : 2;
char b : 3;
char c : 7;

};
显然都不是我们期望的,如果按照正常的内存对齐规则,这两个结构体大小均应该为3才对,那么问题出在哪了呢?首先通过这种现象我们可以肯定的是:带有' 位域' 的结构体并不是按照每个域对齐的,而是将一些位域成员' 捆绑' 在一起做对齐的。
1) 以foo2为例,这个结构体中所有的成员都是char 型的,而且三个位域占用的总空间为6 bit < 8 bit(1 byte),这时编译器会将这三个成员' 捆绑' 在一起做对齐,并且以最小空间作代价,这就是为什么我们得到sizeof(struct foo2) = 1这样的结果的原因了。
2) 再看看foo3这个结构体,同foo2一样,三个成员类型也都是char 型,但是三个成员位域所占空间之和为9 bit > 8 bit(1 byte),这里位域是不能跨越两个成员基本类型空间的,这时编译器将a 和b 两个成员' 捆绑' 按照char 做对齐,而c 单独拿出来以char 类型做对齐,这样实际上在b 和c 之间出现了空隙,但这也是最节省空间的方法了。我们再看一种结构体定义:
struct foo4 {
char a : 2;
char b : 3;
int c : 1;
};

在foo4中虽然三个位域所占用空间之和为6 bit < 8 bit(1 byte) ,但是由于char 和int 的对齐系数是不同的,是不能捆绑在一起,那是不是a 、b 捆绑在一起按照char 对齐,c 单独按照int 对齐呢。