#pragma pack(push, 1) 与 #pragma pack(pop)
·
#pragma pack(push, 1) 和 #pragma pack(pop) 是 C/C++ 中用于控制结构体内存对齐(packing)的编译器指令,目的是强制取消默认的内存对齐填充,使结构体成员紧密排列。
tips:避免在 packed 结构体中包含非字节类型的大成员(如 int、double),除非确定目标平台支持非对齐访问
1. #pragma pack(push, 1)
#pragma pack:告诉编译器如何对齐结构体成员。push:将当前的对齐设置压入栈中保存(以便后续恢复)。, 1:设置新的对齐方式为 1 字节对齐(即不进行任何填充)。
作用:从这一行开始,所有结构体都按 1 字节对齐(成员之间无空隙)。
2. 举个栗子:
#pragma pack(push, 1)
typedef struct {
uint8_t mod_behavior; // 1 byte
uint8_t mod_type; // 1 byte
uint8_t mod_idx; // 1 byte
uint8_t mod_len; // 1 byte
} SmallPackHead; // 总大小 = 4 bytes(无填充)
typedef struct {
SmallPackHead head; // 4 bytes(因为上面设置了 pack(1))
const uint8_t *mod_buf; // 指针(通常是 4 或 8 bytes)
} ModPack;
#pragma pack(pop)
- 如果没有
#pragma pack(1),某些编译器可能会在head后插入填充字节以对齐指针(例如在 32 位系统上让mod_buf地址是 4 的倍数)。 - 但有了
pack(1),ModPack的布局就是:[head:4 bytes][mod_buf:4/8 bytes] → 无填充
3. #pragma pack(pop)
pop:从之前保存的栈中恢复之前的对齐设置。这样后续定义的其他结构体不受影响,保持项目原有的对齐规则。
Why
- 协议解析 / 网络通信 / 二进制文件格式: 数据包格式严格规定字段位置和长度(如你这里的
SmallPackHead可能是通信协议头),必须确保sizeof(SmallPackHead) == 4,不能有额外填充 - 与硬件寄存器映射: 硬件寄存器地址是固定的,结构体必须精确匹配内存布局
- 跨平台数据交换: 避免不同编译器/架构的默认对齐差异导致数据错位
再举个栗子:
#include <stdio.h>
#include <stdint.h>
// 默认对齐(通常 4 字节对齐)
typedef struct {
uint8_t a;
uint32_t b;
} DefaultAlign;
#pragma pack(push, 1)
typedef struct {
uint8_t a;
uint32_t b;
} PackedStruct;
#pragma pack(pop)
int main() {
printf("Default: %zu bytes\n", sizeof(DefaultAlign)); // 输出 8(1+3 padding+4)
printf("Packed: %zu bytes\n", sizeof(PackedStruct)); // 输出 5(1+4)
}
更多推荐


所有评论(0)