在其通用类型属性中,GCC 提供packed
:
此属性附加到
struct
[...] 类型定义,指定放置其每个成员(除了零宽度位字段)以最小化所需的内存。这 相当于指定packed
每个成员的属性。
此外,根据 C18 标准(§ 6.7.2.1, 15-17):
在结构对象中,非位域成员 [...] 的地址按声明顺序递增。指向结构对象的指针,经过适当转换,指向其初始成员 [...],反之亦然。结构对象内可能有未命名的填充,但不是在其开头。[...] 结构末尾可能有未命名的填充 [...]。
因此,鉴于结构的开头没有填充,packed
在其第一个成员上使用似乎是多余的。反过来(这就是我的问题所在),在除第一个packed
成员之外的所有成员上使用似乎不必要地复杂,并且等同于在结构本身上使用(我们假设所有成员都是整数类型)。packed
但是,我多次遇到类似于以下的代码:
struct S {
unsigned a;
unsigned b __attribute__ ((__packed__));
unsigned c __attribute__ ((__packed__));
unsigned d __attribute__ ((__packed__));
};
我无法弄清楚为什么作者更喜欢这样的斗争
struct S {
unsigned a;
unsigned b;
unsigned c;
unsigned d;
} __attribute__ ((__packed__));
packed
第一个成员会改变的结构本身的对齐问题吗?它是否来自我没有考虑过的填充和对齐以外的其他东西(例如旧版本的 GCC 中的怪癖)?另一方面,如果它们是等效的,我怎么能确定它,因为文档是恕我直言,在这里没有什么帮助?
虽然这不是它们等效的有效证据,但我尝试struct
为各种架构(x86、x86_64、Aarch64)编译这两个 s,它们似乎总是共享相同的布局。