#pragma pack(push, 1)#pragma pack(pop)C/C++ 中用于控制结构体内存对齐(packing)的编译器指令,目的是强制取消默认的内存对齐填充,使结构体成员紧密排列
tips:避免在 packed 结构体中包含非字节类型的大成员(如 intdouble),除非确定目标平台支持非对齐访问

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

  1. 协议解析 / 网络通信 / 二进制文件格式: 数据包格式严格规定字段位置和长度(如你这里的 SmallPackHead 可能是通信协议头),必须确保 sizeof(SmallPackHead) == 4,不能有额外填充
  2. 与硬件寄存器映射: 硬件寄存器地址是固定的,结构体必须精确匹配内存布局
  3. 跨平台数据交换: 避免不同编译器/架构的默认对齐差异导致数据错位

再举个栗子:

#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)
}
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐