简体   繁体   English

跨编译器的C结构对齐和可移植性

[英]C struct alignment and portability across compilers

Assuming the following header file corresponding to, for example, a shared library. 假设以下头文件对应于例如共享库。 The exported function takes a pointer to a custom structure defined in this header: 导出的函数获取指向此标头中定义的自定义结构的指针:

// lib.h

typedef struct {
  char c;
  double d;
  int i;
} A;

DLL_EXPORT void f(A* p);

If the shared library is built using one compiler and then is used from C code built with another compiler it might not work because of a different memory alignment, as Memory alignment in C-structs suggests. 如果共享库是使用一个编译器构建的,然后是从使用另一个编译器构建的C代码中使用的,那么由于不同的内存对齐可能无法工作,因为C-struct中的内存对齐表明。 So, is there a way to make my structure definition portable across different compilers on the same platform? 那么,有没有办法让我的结构定义可以在同一平台上的不同编译器中移植?

I am interested specifically in Windows platform (apparently it does not have a well-defined ABI), though would be curious to learn about other platforms as well. 我特别感兴趣的是Windows平台(显然它没有明确定义的ABI),但也很想了解其他平台。

TL;DR in practice you should be fine. TL; DR在实践中你应该没事。

The C standard does not define this but a platform ABI generally does. C标准没有定义这个,但ABI通常会这样做。 That is, for a given CPU architecture and operating system, there can be a definition for how C maps to assembly that allows different compilers to interoperate. 也就是说,对于给定的CPU体系结构和操作系统,可以定义C如何映射到汇编,以允许不同的编译器进行互操作。

Struct alignment isn't the only thing that a platform ABI has to define, you also have function calling conventions and stuff like that. 结构对齐不是平台ABI必须定义的唯一内容,您还有函数调用约定和类似的东西。

C++ makes it even more complex and the ABI has to specify vtables, exceptions, name mangling, etc. C ++使它变得更加复杂,ABI必须指定vtable,异常,名称修改等。

On Windows I think there are multiple C++ ABIs depending on compiler but C is mostly compatible across compilers. 在Windows上我认为有多个C ++ ABI取决于编译器,但C大多数兼容编译器。 I could be wrong, not a Windows expert. 我错了,不是Windows专家。

Some links: 一些链接:

Anyway the bottom line is that you're looking for your guarantee in the platform/compiler ABI spec, not the C standard. 无论如何,底线是您在平台/编译器ABI规范中寻找您的保证,而不是C标准。

The only way to know for sure is to consult the documentation of the compilers in question. 唯一可以确定的方法是查阅相关编译器的文档。 However, it is usually the case that C struct layout (except, as you say, for bitfields) is defined by an ABI description for the environment you're using, and C compilers will tend to follow the native ABI. 但是,通常情况下,C结构布局(除了,如您所说,对于位域)是由您正在使用的环境的ABI描述定义的,并且C编译器将倾向于遵循本机ABI。

Not only that it is not guarantied, but even if you use the same compiler there might be differences due to different compiler switches used in the build, or if you use different versions of the same compiler and same switches (happened in an embedded compiler I worked on). 它不仅没有保证,但即使您使用相同的编译器,也可能由于构建中使用的不同编译器开关而存在差异,或者如果您使用相同编译器和相同开关的不同版本(发生在嵌入式编译器中)从事)。

You need to make make sure the structs are represented exactly the same, use switches, #pragmas, whatever the compilers gives you. 您需要确保结构表示完全相同,使用开关,#pragmas,无论编译器给你什么。

My advice - to stay way from this altogether. 我的建议 - 完全避免这种情况。 Pass your arguments in the function, not wrapped within a struct. 在函数中传递参数,不包含在结构中。

And even in this simple form, if you deal with two compilers, it's not trivial. 即使以这种简单的形式,如果你处理两个编译器,它也不是微不足道的。 You need to make sure that an int takes the same number of bytes, for example. 例如,您需要确保int占用相同的字节数。 Also calling conevntion - arguments order - from left to right or from right to left - can differ between compiler. 同样调用conevntion - 参数顺序 - 从左到右或从右到左 - 在编译器之间可能不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM