位域(Bit-field)
位域是 C 语言结构体中按 bit 为单位分配内存的语法,打破”以字节为最小单位”的规则。
基本语法
struct Register {
uint8_t enable : 1; // 占 1 bit(范围 0~1)
uint8_t mode : 3; // 占 3 bit(范围 0~7)
uint8_t priority : 4; // 占 4 bit(范围 0~15)
}; bit → sizeof(struct Register) == 1 字节。
两种特殊写法
| 写法 | 作用 | 示例 |
|---|---|---|
无名位域 : N | 保留/跳过 N 个 bit(Reserved) | uint8_t : 3; |
零长位域 : 0 | 强制下一个成员对齐到下一存储单元边界 | uint8_t : 0; |
// 无名位域:填充保留位
struct {
uint8_t a : 2;
uint8_t : 3; // 保留 3 bit
uint8_t b : 3;
};
// 零长位域:强制断行
struct Example {
uint8_t a : 3;
uint8_t : 0; // 下一个成员从新 byte 开始
uint8_t b : 3;
};核心应用场景
- 极限压缩内存 — 多个布尔标志合并到一个字节,嵌入式/海量数据场景省 RAM
- 硬件寄存器映射 — 寄存器按 bit 划分功能,位域直接对应硬件位
// 串口控制寄存器映射
typedef struct {
uint32_t TXEN : 1; // 发送使能
uint32_t RXEN : 1; // 接收使能
uint32_t BAUDS : 4; // 波特率选择
uint32_t : 2; // 保留
uint32_t parity: 2; // 校验位
} UART_CR_t;四大坑点
符号陷阱
用 int 或未显式写 unsigned 声明 1-bit 位域:
struct Flag {
int is_ok : 1; // ❌ 有符号!取值范围 -1 和 0,不是 1 和 0
};铁律:标志位必须用
unsigned int或uint8_t/uint32_t。
不能取地址
CPU 按字节编址,无法为单个 bit 分配指针:
struct Register reg;
uint8_t *p = ®.enable; // ❌ 编译报错跨平台可移植性差
C 标准不规定字节内 bit 排列顺序(LSB vs MSB)。不同编译器可能把第一个成员放在 bit 0 或 bit 7。禁止直接跨平台传输位域结构体。
性能开销
修改位域时编译器生成”读-改-写”指令序列:读整个字节 → 清零目标 bit → 写入新值 → 写回内存。比普通变量稍慢,本质是空间换时间。