为啥这个结构不打包?
Posted
技术标签:
【中文标题】为啥这个结构不打包?【英文标题】:Why would this struct not pack?为什么这个结构不打包? 【发布时间】:2021-12-15 21:27:29 【问题描述】:也许我对“打包”属性的性质有一些误解,但我的理解是下面的结构应该打包到 16 个字节,而不是通常填充的 24 个字节。我可以验证是否正在应用打包属性(通常),因为我在同一个头文件中定义了另一个结构,该结构从 16 字节压缩到 10 字节。编译器是否有任何理由会忽略该属性而不通过警告指示?
为了澄清,当我说它似乎没有打包时,我是基于 sizeof(foo) 的输出,它返回 24 而不是预期的 16。有问题的代码在简单/粗略的范围内目前自定义内核的工具非常有限,所以我一直依赖于通过打印到屏幕进行基本调试。
我正在使用 GCC 10.3.0(在 ubuntu 上)。
typedef struct
uint16_t m1;
uint16_t m2;
uint8_t m3;
uint8_t m4;
uint16_t m5;
uint32_t m6;
uint32_t m7;
__attribute__((packed)) foo;
【问题讨论】:
你是说这不会为你打包到 16 个字节吗?对我有用,你用的是什么编译器? 用 gcc 和 clang 看起来不错。 godbolt.org/z/EKEG6Y1PP 编辑问题以提供minimal reproducible example,包括结构大小为 24 字节的证据。 我注意到这些标准类型不是来自您代码中的<stdint.h>
,而是来自您自己的"types.h"
。您是否 100% 确定您的类型定义解析为您认为的数据大小?我的猜测是 sizeof(unsigned long)
实际上是 8。这可以解释你得到的 8 个额外字节。
不客气。请记住,99% 的情况下,当您认为编译器有问题时,事实证明这是您的代码中的错误。 ;)
【参考方案1】:
正如 paddy 所指出的,问题是 uint64_t
的类型定义不正确,导致每个额外的 4 个字节,而结构中的 2 个导致额外的 8 个字节。
【讨论】:
【参考方案2】:注意事项:虽然__attribute__((packed))
由 GCC 定义,但这是一个定义的实现 扩展,而不是标准 C 语言的一部分。
因此,虽然这应该与 GCC(或 GCC 衍生产品)一起工作,但它不一定适用于任何其他编译器 - 因此,如果您依赖打包,则需要确保它按预期包装。
【讨论】:
我没有投反对票,但是不支持 gcc__attribute__
的编译器不会让代码编译。如果它让代码通过,我希望它全部打包结构。与 #pragma pack(1)
相反,即使编译器不支持它也会编译。
这不是问题的答案。在输入此答案时,问题表明 OP 正在使用 GCC 10.3.0,它支持 __attribute__((packed))
,因此缺乏支持并不能解释观察到的行为。任何不支持该扩展的编译器都应该发布关于该事实的诊断。以上是关于为啥这个结构不打包?的主要内容,如果未能解决你的问题,请参考以下文章