C语言应用笔记:能降低结构体内存占用的位域操作
在C语言中,结构体位域(Bit Fields)允许精确控制结构体成员占用的内存位数,这在嵌入式系统、网络协议等内存敏感场景中非常有用。以下是位域的核心知识点和示例:
位域定义语法
struct 结构体名 {
类型 [成员名] : 位宽;
};
- 类型:必须为整型(int、unsigned int、signed int)
- 位宽:指定成员占用的比特数(0 ≤ 位宽 ≤ 类型位数)
- 匿名位域:无成员名的位域,用于占位填充(如 unsigned int : 4;)
关键特性
- 内存压缩:多个位域成员可能共享同一存储单元
- 地址不可取:无法对位域成员使用取地址运算符 &(因小于1字节)
- 赋值行为:无法赋予超出bit位的值
基础示例
#pragma pack(1) // 1字节对齐
typedef struct {
// 占1个字节
uint8_t byte;
// 共占4个字节
uint32_t a : 2;
uint32_t b : 4;
uint32_t c : 6;
} example;
#pragma pack()
static example t = {
.a = 2, .b = 5, .c = 6,
};
int main(void) {
printf("example size: %d\r\n", sizeof(example));
printf("a = %d\r\n", t.a);
printf("b = %d\r\n", t.b);
printf("c = %d\r\n", t.c);
return 0;
}
高级用法
将原始数据拷贝给带位域成员的结构体变量,可自动解析出占用不同bit位的数值,省去了手动解析的步骤。具体实现如下:
#pragma pack(1)
// 定义占用2字节的位域结构体
typedef struct {
uint16_t a : 5; // 5位 (0-31)
uint16_t b : 7; // 7位 (0-127)
uint16_t c : 4; // 4位 (0-15)
} BitFieldStruct;
#pragma pack()
int main() {
// 定义位域结构体变量
BitFieldStruct data;
// 十六进制值: 1010 1011 1100 1101
uint16_t raw_value = 0xABCD;
// 使用内存拷贝确保正确赋值
memcpy(&data, &raw_value, sizeof(data));
// 打印结果
printf("原始值: 0x%04X (%d)\n", raw_value, raw_value);
printf("结构体大小: %d 字节\n", sizeof(data));
printf("解析结果:\n");
printf(" a (5位): %d\n", data.a); // 低5位: 0b01101 = 13
printf(" b (7位): %d\n", data.b); // 中间7位: 0b1011110 = 94
printf(" c (4位): %d\n", data.c); // 高4位: 0b1010 = 10
return 0;
}
输出结果
原始值: 0xABCD (43981)
结构体大小: 2 字节
解析结果:
a (5位): 13
b (7位): 94
c (4位): 10