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



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

我知道64位程序不能调用32位库,但我仍然认为结构布局可以在相同位的编译器中有所不同。

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

  • 整型的宽度和端序。
  • 浮点类型的宽度和表示。
  • 对齐约束,规定结构中是否存在填充。
  • 参数如何传递给函数(在寄存器和堆栈中)。

例如,在x86_64处理器体系结构(即64位PC的处理器体系结构)上,有两种流行的ABI: Microsoft x64调用约定,用于Windows,以及System V amd64 ABI (PDF -你特别要问的部分在§3.1"机器接口"中),用于其他任何地方。32位x86历来有更多的碎片。

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

相关内容

最新更新