#pragma pack
是编译器指令,用于控制结构体(struct)或联合体(union)的内存对齐方式。
一、#pragma pack(1)
的作用
1. 取消对齐优化
-
使用
#pragma pack(1)
:强制按 1字节对齐,取消所有填充字节,成员变量紧密排列
每个成员的实际对齐值 =min(n, 成员的自然对齐值)
-
uint8_t
(1 字节):自然对齐值为 1uint16_t
(2 字节):自然对齐值为 2
uint32_t
(4 字节):自然对齐值为 4double
(8 字节):自然对齐值为 8
#pragma pack(1)
typedef struct {
uint8_t a; // 1字节
uint32_t b; // 4字节
uint16_t c; // 2字节
} UnalignedStruct; // 总大小 = 1 + 4 + 2 = 7字节
#pragma pack()
地址 : 0x00 0x01 0x02 0x03 0x04 0x05 0x06
内容 : [a] [b0] [b1] [b2] [b3] [c0] [c1]
2. 对比默认对齐
默认行为:编译器会根据成员变量类型自动插入填充字节以实现对齐。
对齐值等于其最宽成员的对齐值。
// 默认对齐(通常为4字节对齐)
typedef struct {
uint8_t a; // 1字节 + 3字节填充
uint32_t b; // 4字节 必须从 4 的倍数地址开始
uint16_t c; // 2字节 + 2字节填充
} AlignedStruct; // 总大小 = 1 + 3(pad) + 4 + 2 + 2(pad) = 12字节
-
总大小要求:必须是 4 的倍数 → 最近的是 12 字节(末尾填充)
地址 : 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B
内容 : [a] pad pad pad [b0] [b1] [b2] [b3] [c0] [c1] pad pad
二、何时使用 #pragma pack(1)
1. 跨平台/跨设备数据交换
-
场景:通过网络传输二进制数据、读写文件、与硬件寄存器交互。
-
必要性:确保数据布局严格一致,避免不同编译器或硬件对齐规则差异。
-
示例:定义网络协议头:
#pragma pack(1)
typedef struct {
uint16_t type; // 2字节 占用 0x00-0x01
uint32_t length; // 4字节 占用 0x02-0x05
uint8_t flags; // 1字节 占用 0x06
} PacketHeader; // 总大小 = 2 + 4 + 1 = 7字节
#pragma pack()