2026/9/14 11:15:07

[C][KEIL5][IAR] 全局取消结构体对齐

[C][KEIL5][IAR] 全局取消结构体对齐 文章目录一、 引言二、 结构体对齐的原理与影响2.1 什么是字节对齐2.2 对齐与不对齐的编译对比2.3 对齐策略对 RAM 与 Flash 的影响三、 实战示例局部取消对齐3.1 使用 __attribute__((packed))3.2 使用 #pragma pack(n)3.3 两种方式的对比与选型建议四、 总结一、 正常编译二、 -fpack-struct 全局取消结构体对齐三、 结论结构体字节不进行对齐的用途1减小内存占用的空间2直接将结构体作为通信协议在低带宽下通讯3字节对齐增加RAM大小减少Flash大小反之减少RAM大小增大Flash大小。四、其他局部对其方式1 使用 __attribute__((packed))(2) 利用伪指令 #pragma pack (n) 可以动态的调整内存对齐的方式一、 引言本文以嵌入式开发中常见的结构体内存对齐问题为切入点通过对比正常编译与使用-fpack-struct取消对齐后的内存占用差异帮助读者理解字节对齐对 RAM、Flash 及通信协议设计的影响并介绍__attribute__((packed))与#pragma pack(n)两种局部控制方式。建议字数300–500 字二、 结构体对齐的原理与影响2.1 什么是字节对齐介绍编译器默认按成员最大对齐单位进行填充的机制以及对齐带来的内存开销。建议字数400–600 字2.2 对齐与不对齐的编译对比结合正文中正常编译与-fpack-struct的 RO/RW/ROM 数据两种模式下的内存占用对比如下表所示指标正常编译-fpack-struct差异差异原因Total RO SizeCode RO Data2002419.55kB2241621.89kB23922.34kB取消对齐后编译器需生成额外的位操作/字节拼接指令代码量增加Total RW SizeRW Data ZI Data1473614.39kB1460814.27kB-128-0.12kB结构体不再填充对齐字节全局/静态数据区占用减小Total ROM SizeCode RO Data RW Data2032819.85kB2271222.18kB23842.33kB代码段增长幅度大于数据段节省整体 ROM 占用上升可以看到-fpack-struct虽然能略微减小 RW 数据区但会显著增大代码体积因此更适合按需局部使用而非全局开启。建议字数400–600 字2.3 对齐策略对 RAM 与 Flash 的影响解释「字节对齐增加 RAM 大小、减少 Flash 大小反之亦然」的权衡关系。建议字数300–500 字三、 实战示例局部取消对齐3.1 使用__attribute__((packed))下面给出一个完整的结构体定义示例对比默认对齐与使用__attribute__((packed))取消对齐后的内存占用差异#includestdio.h// 默认对齐方式structTestDefault{charc;// 1 字节inti;// 4 字节shorts;// 2 字节};// 使用 __attribute__((packed)) 取消对齐structTestPacked{charc;// 1 字节inti;// 4 字节shorts;// 2 字节}__attribute__((packed));intmain(void){printf(sizeof(struct TestDefault) %zu\n,sizeof(structTestDefault));printf(sizeof(struct TestPacked) %zu\n,sizeof(structTestPacked));return0;}在 32 位平台上默认对齐时struct TestDefault因填充字节占用 12 字节而struct TestPacked取消对齐后仅占用 7 字节1 4 2内存节省约 42%。适用场景需要将结构体直接映射为通信协议报文或文件记录格式时保证内存布局与定义完全一致在内存受限的嵌入式环境中需要压缩结构体占用空间时需要跨平台、跨编译器保持结构体二进制布局稳定时。注意事项取消对齐后成员访问可能产生非对齐访问在部分 ARM 平台上会触发硬件异常或降低访问效率编译器需要生成额外的位操作/字节拼接指令来访问非对齐成员代码体积和运行开销会相应增加结构体指针不能随意强转为成员类型指针否则可能引发未定义行为该属性是 GCC/Clang 扩展非标准 C 语法移植到其他编译器时需确认兼容性。建议字数300–500 字3.2 使用#pragma pack(n)结合正文代码演示动态调整对齐方式及恢复默认对齐的方法。建议字数400–600 字3.3 两种方式的对比与选型建议对比 packed 与 pragma pack 的优缺点给出实际项目中的选型建议。建议字数300–500 字四、 总结回顾全文要点强调在低带宽通信与内存优化场景下合理使用取消对齐手段。建议字数200–300 字一、 正常编译Total RO Size (Code RO Data) 20024 ( 19.55kB) Total RW Size (RW Data ZI Data) 14736 ( 14.39kB) Total ROM Size (Code RO Data RW Data) 20328 ( 19.85kB)二、 -fpack-struct 全局取消结构体对齐Total RO Size (Code RO Data) 22416 ( 21.89kB) Total RW Size (RW Data ZI Data) 14608 ( 14.27kB) Total ROM Size (Code RO Data RW Data) 22712 ( 22.18kB)三、 结论结构体字节不进行对齐的用途1减小内存占用的空间结构体默认进行对齐占用的空间比结构体内部成员变量字节加起来大如果取消字节对齐可以减小一部分空间。2直接将结构体作为通信协议在低带宽下通讯在不同的平台下保证结构体内基本数据的长度相同同时取消结构体的对齐就可以将定义的数据格式结构体直接作为数据通信协议使用。3字节对齐增加RAM大小减少Flash大小反之减少RAM大小增大Flash大小。jianqiang.xue四、其他局部对其方式1 使用attribute((packed))例如structTEST{shortx;inty;}__attribute__((packed));(2) 利用伪指令 #pragma pack (n) 可以动态的调整内存对齐的方式#pragmapack(n)// 编译器将按照n个字节对齐#pragmapack()// 恢复先前的pack设置,取消设置的字节对齐方式#pragmapack(pop)// 恢复先前的pack设置,取消设置的字节对齐方式#pragmapack(1)// 按1字节进行对齐 即不行进行对齐#pragmapack(1)typedefstructTestNoAlign{unsignedcharu8_test1;unsignedintu32_test2;doubled8_test3;staticintsta_test5;// 静态变量存储在静态区不在栈中所以sizeof运算符不会进行计算其占用的空间此外c语言不只支持结构体内定义static类型的变量但是c支持。}TestNoAlign;#pragmapack()