当在 DLL 或 .so 中调用函数时,当编译器使用对齐和填充进行自己的结构布局时,为什么传递结构是可靠的?

Joe*_*e C 6 c struct

c 语言结构中的 AFAIK 会按照编译器认为合适的方式进行布局、对齐和填充。这就是为什么你不能依赖一个 c 程序来使用来自另一个 c 程序的结构。例如,您不能将结构另存为另一个 c 程序将读取并转换为同一个结构的二进制文件。您也许可以使用这样的打包结构,但这并不是一个很好的做法。
所以我很惊讶地发现 .so 和 DLL 文件具有将复杂结构(其引用)作为参数的 c 函数。至少我公司的产品是这样做的。这是可靠的,这是好的做法吗?是否有一些大小、对齐和填充都相同的结构布局的新标准?

我知道 64 位程序不能调用 32 位库,但我仍然认为结构布局可能因相同位的编译器而异。

Gil*_*il' 3

对于给定的处理器类型和给定的操作系统,通常有一个标准ABI(应用程序二进制接口),它指定以下内容:

\n
    \n
  • 整数类型的宽度和字节顺序。
  • \n
  • 浮点类型的宽度和表示形式。
  • \n
  • 对齐约束,决定结构中是否存在填充。
  • \n
  • 参数如何传递给函数(在寄存器中和堆栈上)。
  • \n
\n

例如,在x86_64处理器架构(即 64 位 PC 的处理器架构)上,有两种流行的 ABI: Windows 上使用的Microsoft x64 调用约定System V amd64 ABI ( PDF \xe2\x80\x94您具体询问的部分位于 \xc2\xa73.1 \xe2\x80\x9cMachine interface\xe2\x80\x9d) 中,在其他地方使用。32 位 x86 历史上有更多碎片。

\n

因此,一般来说,如果您在默认模式下为同一平台(处理器和操作系统)使用不同的编译器,它们将为结构生成相同的布局,并且它们将生成与以下方式兼容的函数调用代码:其他编译器编译的函数读取它们的参数。当您混合不同的平台时,例如在嵌入式设备上编写结构并尝试在 PC 上读取它,就会出现问题。

\n