结构体可以用来实现位段,,在C语言中,多数情况下按照一个字节的整数倍为单位处理数据,也就是必须是以8位为单位处理数据,,比如一个char
为8位,一个int
可能为32位.。位段使我们可以按 “任意” 位处理数据,比如7位, 6位等。我们可以把结构体中某个字段所占用的二进制个位数设为特定的值:
struct data {
unsigned int fieldA : 8;
unsigned int fieldB : 4;
unsigned int fieldC : 2;
unsigned int fieldD : 1;
};
在赋值时可以使用:packed_data.fieldB = n;
我们不必担心n
的值太长, 以致不能放入fieldB
位段中, C 编译器会自动地仅取出n
的低四位, 把它赋值给packed_data.fieldB
。取出位段的值也自动地处理的, 因此语句n = packed_data.fieldB;
将从packed_data
中取出type
位段, 并把它的值赋给 n
。假设n
为17,那么编译器(Xcode)就会给出警告⚠️:Implicit truncation from 'int' to bit-field changes value from 17 to 1
。
注意:
- 位段成员必须声明为 int,signed int,unsigned int (C11中只要是整型就可以, 包括int32_t uint16_t等) ,整个位段可使用的位数即该类型在当前硬件中所占位数。由于int类型具体当作有符号类型还是无符号类型由编译器决定,所以最好将位段成员声明为
signed int
或unsigned int
类型。 - 标识符后是一个冒号和一个整数,该整数指定位段成员所占位数。
- 编译器可能将位段成员的长度限制在一个int值长度之内, 所以16位机器上的位段不能用于32位机器。
- 位段成员在内存中可能从左向右分配也可能从右向左分配。
- 几个邻近的位段成员可能被拼接到同一可寻址存储单元。
- 在包含位段的结构中, 也可以包括 “通常的” 数据类型。
- 可以指定无名位段, 使得一个字中的某些位被 “跳过”。如:
struct data {
unsigned int fieldA :4;
unsigned int :3;
unsigned int fieldB :9;
};
//无名位段规定了fieldA和fieldB间隔三位。