c - 打包结构会影响子结构吗?

标签 c windows visual-studio-2015

我们最近发现一些代码提交到我们的代码库,大致如下:

#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 是否由于几乎可以肯定已提前声明这一事实而“受到保护”免受打包?如果作为外层申报的一部分申报,那么是否需要装箱?

最佳答案

来自relevant documentation :

pack takes effect at the first struct, union, or class 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 gccVC++按预期行事。并不是说我特别惊讶——任何不同的东西都会破坏类型系统(使用指向打包结构成员的指针实际上会提供指向不同于其类型所说的东西的指针1)。

一般的想法是:一旦你完成定义一个struct,它的二进制布局是固定的,它的任何实例化都将符合它,包括打包结构的子对象。当前的 #pragma pack 值仅在定义新结构时被考虑,并且在这样做时成员的二进制布局是一个固定的黑框。


注释

  1. 老实说,这是有点以 x86 为中心的观点;具有更强对齐要求的机器会反对甚至指向布局正确但未对齐结构的指针也不符合犹太教规:尽管字段相对于给定指针的偏移量是正确的,但它们并不是真正可以按原样使用的指针。

    OTOH,给定一个指向未对齐对象的指针,您始终可以检测到它是未对齐的,并将它memcpy 到正确对齐的位置,因此它不像假设的指向打包对象的指针那么糟糕,除非您碰巧知道其父级的包装,否则其布局实际上是未知的。

关于c - 打包结构会影响子结构吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49125165/

相关文章:

visual-studio-2015 - 使用 MSBuild 命令行创建 APK 错误(PackageForAndroid 或 SignAndroidPackage)

c# - 在c#(VS2015)中查看垃圾回收历史

c++ - 这个表达式计算什么

c - C 中 1 的无效写入大小

c - 字符串文字 : Where do they go?

java - 如何终止通常使用 ProcessBuilder 创建的进程

c - 两个不同的 for 循环之间的 Printf 不起作用

c# - 修改正在运行的可执行文件的资源内容

c++ - 提高 Windows 应用程序的性能

c++ - vs2015 上的 STL 列表性能不佳,同时删除包含指向自身在列表中位置的迭代器的节点