我们最近发现一些代码提交到我们的代码库,大致如下:
#pragma pack(push,1)
struct xyzzy {
BITMAPINFOHEADER header;
char plugh;
long twisty;
} myVar;
我的问题是:打包只应用于直接结构,还是它也可能影响BITMAPINFOHEADER
的打包。我看不到后一种情况非常有用,因为它会使结构不同于您从 Windows API 调用中获得的结构。恰当的例子,让我们假设结构是:
typedef struct {
char aChar;
DWORD biSize;
} BITMAPINFOHEADER;
该结构与 Windows 的默认八个打包相比会有很大不同(无论如何是 32 位,对于 64 位可能是十六个)。
BITMAPINFOHEADER
是否由于几乎可以肯定已提前声明这一事实而“受到保护”免受打包?如果作为外层申报的一部分申报,那么是否需要装箱?
最佳答案
pack
takes effect at the firststruct
,union
, orclass
declaration after the pragma is seen.pack
has no effect on definitions.
header
是成员定义,所以不受影响。
it was declared as part of the outer declaration, would it be subject to the packing then?
是的,因为它是一个 struct
声明。
此外,正如 Lightness Races in Orbit 在评论中所说,可以在之前找到更有说服力的措辞:
To pack a class is to place its members directly after each other in memory.
即它没有说明这些成员本身包含的内容,可能是数据和/或填充。事实上(如上文所探讨的)紧缩性与类型相关联,这一事实似乎强化了这一点
不过,文档已经够模糊了,所以最好测试一下这个解释是否正确; both gcc和 VC++按预期行事。并不是说我特别惊讶——任何不同的东西都会破坏类型系统(使用指向打包结构成员的指针实际上会提供指向不同于其类型所说的东西的指针1)。
一般的想法是:一旦你完成定义一个struct
,它的二进制布局是固定的,它的任何实例化都将符合它,包括打包结构的子对象。当前的 #pragma pack
值仅在定义新结构时被考虑,并且在这样做时成员的二进制布局是一个固定的黑框。
注释
老实说,这是有点以 x86 为中心的观点;具有更强对齐要求的机器会反对甚至指向布局正确但未对齐结构的指针也不符合犹太教规:尽管字段相对于给定指针的偏移量是正确的,但它们并不是真正可以按原样使用的指针。
OTOH,给定一个指向未对齐对象的指针,您始终可以检测到它是未对齐的,并将它
memcpy
到正确对齐的位置,因此它不像假设的指向打包对象的指针那么糟糕,除非您碰巧知道其父级的包装,否则其布局实际上是未知的。
关于c - 打包结构会影响子结构吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49125165/