每日一学26
位域
C语言可以在一个结构体中以二进制位为单位来指定其成员所占用内存长度,这种以位单位的成员就称为位域(bit field)。如何以位作为单位来访问数据呢?这样可以更高效的使用存储空间,方法就是使用位域,这样就可以在一个字节中分别存放多个信息。
struct data //定义结构体
{
unsigned n1:6; // n1 占 6 个位
unsigned n2:4; // n2 占 4 个位
unsigned n3:4; // n3 占 4 个位
unsigned n4:2; // n4 占 2 个位
} mydata;
在使用位域时,需要注意以下情况:
(1)一个位域必须存储在同一个存储单元中,不能跨两个单元。我们可以闲置没有使用的存储单元,但是当剩余存储单元放不下时,就要从下一个单元开始存放。而且定义的每一个位域长度不能超过存储单元。
(2)位域名为无名位域时,空间会被闲置。例如:struct date //定义结构体
{
unsigned a:2; // a 占 2 个位
unsigned :2; // 空 2 个位
unsigned b:1; // b 占 1 个位
} mydate;
第 2 次申请的 2 个空间的位域是闲置不用的,因为没有位域名称。
需要注意的是,无名位域长度为 0 时,它指的是这个字节剩余的部分不再使用,从下个新字节开始存储。例如:struct date //定义结构体
{
unsigned a:2; // a 占 2 个位
unsigned :0; // 从下一个新字节开始存储
unsigned b:1; // b 占 1 个位
} mydate;
(3)一个结构体中既可以定义位域成员,也可以同时定义一般的结构体成员。例如:struct date //定义结构体
{
unsigned a:2; // a 占 2 个位
unsigned :0; // 从下一个新字节开始存储
unsigned b:1; // b 占 1 个位
} mydate;
(4)不能定义以位域结构为元素的数组。位域的引用与结构体相同。例如:mydata.a=2; // 赋值
mydata.b=1; // 赋值
需要注意的是,a 只占两位,我们在上面的结构体中有声明,也就是说,a 最大存储的二进制数是 11,转换为十进制就是 3。如果赋值如 mydata.a=10,这并不会报错,但结果就不是期望的 10 了,而是 2,因为 10 的二进制码是 1010,只截取右边两位 10,故结果是 2。
(5)位域也可以参与算术表达式的运算,这时系统会自动将其转换为整型数。位域可以用整型格式符输出。例如:printf("%d\n",mydata.a); // a 以有符号整数形式输出
printf("%u\n",mydata.a); // a 以无符号整数形式输出