`#pragma pack(1)的使用

张开发
2026/5/23 13:53:28 15 分钟阅读
`#pragma pack(1)的使用
#pragma pack(1)和#pragma pack()是编译器指令用于控制结构体或联合体成员在内存中的对齐方式。对齐的基本概念默认情况下编译器为了提高访问效率会对结构体成员进行对齐。例如一个uint16_t类型的成员通常会被放置在 2 字节的整数倍地址上如果前面有奇数个字节的u8成员编译器会在中间插入填充字节padding保证对齐。这样结构体的大小可能大于成员大小之和。#pragma pack(1)的作用#pragma pack(1)强制编译器采用1 字节对齐即取消所有填充成员在内存中紧密排列没有任何空隙。这会使结构体的大小等于成员大小的总和但可能降低 CPU 访问效率尤其是在某些架构上可能产生非对齐访问异常。#pragma pack()的作用#pragma pack()恢复默认的对齐方式通常由编译器设定例如 4 字节或 8 字节对齐。在你问题中的影响在transform.h中你使用了#pragma pack(1)来定义PHYSICALKEY结构体。但是RotaryDial结构体是在ADS1015.h中定义的并且没有使用相同的对齐指令。这导致ADS1015.c编译时RotaryDial采用默认对齐例如 4 字节value成员uint16_t的偏移量可能是 6因为前面有 5 个u8再加 1 字节填充。transform.c编译时由于#pragma pack(1)的影响仍然存在如果transform.h在包含ADS1015.h之前设置了 packRotaryDial结构体在transform.c中也会被强制 1 字节对齐value的偏移量为 5。两个文件对同一结构体的内存布局理解不同导致transform.c访问RotaryDial_l.value时实际读取的是结构体中偏移 5 处的数据而那个位置可能是state或其他值从而得到类似地址的大数。解决方案统一对齐方式在ADS1015.h中的RotaryDial定义前 也加上#pragma pack(1)确保所有文件都使用相同的紧凑布局。调整成员顺序将对齐敏感的成员如uint16_t value放在结构体最前面这样无论对齐方式如何其偏移量始终为 0避免错位。推荐优先尝试方案 2因为改动最小且不会影响其他代码。

更多文章