You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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结构体,头文件的宏保护失效或头文件引用顺序错误,导致你实际引用的是未压缩的结构体版本。

具体排查步骤

  1. 先单独打印各基础类型的大小确认类型定义是否正确:
// 你可以替换为你内核中对应的打印接口
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()
  1. 将结构体重命名为不存在冲突的名称(比如foo_test)后重新测试sizeof的结果,若大小变为16,说明原工程存在同名结构体冲突,排查对应头文件引用逻辑即可。

内容的提问来源于stack exchange,提问作者Chris Waymire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:45:07