C语言的位域(bit-field) 是一种特殊的结构体成员,允许我们按位对成员进行定义,指定其占用的位数。
- 定义位域时可以指定成员的位域宽度,即成员所占用的位数
- 位域的宽度不能超过其数据类型的大小,因为位域必须适应所使用的整数类型
- 位域的数据类型可以是 int 、 unsigned int 、 signed int 等整数类型,也可以是枚举类型-enum
- 位域可以单独使用也可以与其他成员一起组成结构体
- 位域的访问通过 点运算符(.) 来实现,与普通结构体成员相同
- 常用于需要占用一个或几个二级制位的数
- 用1位二进制存放开关量,只有0和1
- 读取非标准文件格式,例如9位的整数
声明方式类似:
struct 位域结构名
{
type [member_name] : width;
...
};
- type:可以是 int(整型) , unsigned int (无符号整型) , signed int (有符号整型)
- member_name: 位域的名称
- width: 位域中位的数量,必须小于等于指定类型的位宽度。 int通常为4个字节(32位)
- 相邻位域字段得类型相同,且位宽之和小于类型得 sizeof 大小,则后面的字段将紧邻前一个字段存储,直到不能容纳位置
- 也可以通过创建一个空域来有意使得某位域从下一个单元开始
int : 2;
下面需要一个案例来简单的实验一下:
int struct_bit_field_demo()
{
struct packed_struct {
unsigned int f1 : 1;
unsigned int f2 : 1;
unsigned int f3 : 1;
unsigned int f4 : 1;
unsigned int type : 4;
unsigned int my_int : 9;
};
struct packed_struct pack;
pack.f1 = 0;
pack.f2 = 1;
pack.f3 = 1;
pack.f4 = 0;
pack.type = 7;
pack.my_int = 255;
printf("f1 : %d \n", pack.f1);
printf("f2 : %d \n", pack.f2);
printf("f3 : %d \n", pack.f3);
printf("f4 : %d \n", pack.f4);
printf("type : %d \n", pack.type);
printf("my_int : %d \n", pack.my_int);
struct
{
unsigned int age : 3;
unsigned int : 1; // 空域
}Age;
Age.age = 4;
printf("Sizeof ( Age ) : %zd \n", sizeof(Age));
printf("Age.age : %d \n", Age.age);
Age.age = 7;
printf("Sizeof ( Age ) : %zd \n", sizeof(Age));
printf("Age.age : %d \n", Age.age);
Age.age = 8; // 二进制表示为 1000 有四位数,超出
printf("Sizeof ( Age ) : %zd \n", sizeof(Age));
printf("Age.age : %d \n", Age.age);
Age.age = 11; // 二进制表示为 1011 有四位数,超出
printf("Sizeof ( Age ) : %zd \n", sizeof(Age));
printf("Age.age : %d \n", Age.age);
struct bs {
unsigned int a : 1;
unsigned int b : 3;
unsigned int c : 4;
}bit , *pbit;
bit.a = 1;
bit.b = 7;
bit.c = 15;
printf("%d , %d , %d \n", bit.a, bit.b, bit.c);
pbit = &bit;
pbit->a = 0; // 用指针的方式重新给a赋值0
pbit->b&=3; // 使用复合位运算符 "&=",相当于 pbit->b = pbit->b&3 , 位域 b 中原有值为7 ,与 3 按 位与 运算的结果为 3 (111&011 = 011)
pbit->c|=1; // 使用复合位运算符 "|=",相当于 pbit->c = pbit->c|1 , 结果为 15 (1111 | 0001 = 1111)
printf("%d , %d , %d \n", pbit->a, pbit->b, pbit->c);
}