位域
位域(bit-field)是结构体中按位分配的成员,用于精确控制内存布局、节省空间、实现硬件寄存器映射等。位域的声明语法是 类型 成员名 : 位数。
基本语法
struct Flags {
unsigned int flag1 : 1; /* 1 位 */
unsigned int flag2 : 1; /* 1 位 */
unsigned int flag3 : 1; /* 1 位 */
unsigned int : 5; /* 5 位填充 */
unsigned int value : 8; /* 8 位 */
};
struct Flags f = {1, 0, 1, 0};
printf("%zu\n", sizeof(f)); /* 通常 4 字节 */
实际应用
IP 头部格式:
struct IPHeader {
unsigned int version : 4; /* IP 版本 */
unsigned int ihl : 4; /* 头部长度 */
unsigned int dscp : 6; /* 服务类型 */
unsigned int ecn : 2; /* 显式拥塞通知 */
unsigned int total_length : 16;
};
硬件寄存器:
struct ControlRegister {
unsigned int enable : 1;
unsigned int mode : 3;
unsigned int : 4; /* 保留位 */
unsigned int status : 8;
};
位域的限制
struct Example {
int a : 3; /* 可以是有符号 */
unsigned int b : 5; /* 推荐用无符号 */
/* int c : 33; */ /* 错误:超过 int 位数 */
};
未命名位域
struct Packed {
unsigned int a : 4;
unsigned int : 4; /* 填充 4 位 */
unsigned int b : 8;
};
零宽度位域
struct Align {
unsigned int a : 4;
unsigned int : 0; /* 强制对齐到下一个存储单元 */
unsigned int b : 4;
};
常见错误
取地址:
struct Flags f;
/* int *p = &f.flag1; */ /* 错误:不能取位域地址 */
位域大小:
struct Bad {
unsigned int a : 33; /* 错误:超过类型位数 */
};
最佳实践
- 位域用
unsigned int类型 - 不假设位域布局(实现相关)
- 位域用于硬件映射、协议解析
- 需要可移植时用掩码和移位替代