GCC 10.3下__attribute__((packed))修饰的结构体未按预期压缩是什么原因
GCC 忽略
__attribute__((packed))属性的常见原因及排查方案 核心原因梳理
- 属性书写位置存在歧义
你当前的写法将__attribute__((packed))放在结构体闭合大括号和typedef别名之间,GCC会默认将该属性判定为修饰typedef的别名,而非结构体类型本身,导致packed属性未实际作用于结构体布局。 - 类型定义不符合预期
你自定义内核中的stdint.h或相关类型定义可能存在修改,比如uint32_t被误定义为8字节类型:按你给出的成员列表,若uint32_t为8字节,总大小刚好为2+2+1+1+2+8+8=24字节,和你测得的结果完全匹配。 - 全局对齐配置覆盖属性
若结构体定义之前的代码中存在#pragma pack(n)、-fpack-struct=n编译选项、全局_Alignas修饰符等对齐配置,且没有在你的结构体定义前重置对齐规则,会覆盖结构体单独声明的packed属性。 - 存在重名结构体定义
你的代码中可能存在另一个未加packed属性的同名foo结构体,头文件的宏保护失效或头文件引用顺序错误,导致你实际引用的是未压缩的结构体版本。
具体排查步骤
- 先单独打印各基础类型的大小确认类型定义是否正确:
// 你可以替换为你内核中对应的打印接口 printk("uint16_t size: %u\n", sizeof(uint16_t)); printk("uint32_t size: %u\n", sizeof(uint32_t));
若uint32_t大小为8,直接修改类型定义即可解决问题。
2. 调整packed属性的书写位置,避免歧义,推荐写法如下:
typedef struct __attribute__((packed)) { uint16_t m1; uint16_t m2; uint8_t m3; uint8_t m4; uint16_t m5; uint32_t m6; uint32_t m7; } foo;
也可以在结构体定义前后显式指定对齐规则:
#pragma pack(1) typedef struct { uint16_t m1; uint16_t m2; uint8_t m3; uint8_t m4; uint16_t m5; uint32_t m6; uint32_t m7; } foo; #pragma pack()
- 将结构体重命名为不存在冲突的名称(比如
foo_test)后重新测试sizeof的结果,若大小变为16,说明原工程存在同名结构体冲突,排查对应头文件引用逻辑即可。
内容的提问来源于stack exchange,提问作者Chris Waymire
相关产品推荐
相关产品推荐

