假设以下头文件对应于(例如)共享库。导出的函数获取指向此标头中定义的自定义结构的指针:
// lib.h
typedef struct {
char c;
double d;
int i;
} A;
DLL_EXPORT void f(A* p);
如果共享库是使用一个编译器构建的,然后是从使用其他编译器构建的C代码中使用的,那么由于内存对齐不同,它可能无效,如Memory alignment in C-structs所示。那么,有没有办法让我的结构定义在同一平台上的不同编译器中可移植?
我对Windows平台特别感兴趣(显然它没有明确定义的ABI),但也很想了解其他平台。
答案 0 :(得分:13)
TL; DR在实践中你应该没事。
C标准没有定义这个,但ABI通常会这样做。也就是说,对于给定的CPU架构和操作系统,可以定义C如何映射到汇编,以允许不同的编译器进行互操作。
结构对齐不是平台ABI必须定义的唯一东西,你也有函数调用约定和类似的东西。
C ++使它变得更加复杂,ABI必须指定vtable,异常,名称修改等。
在Windows上我认为有多个C ++ ABI取决于编译器,但C主要与编译器兼容。我错了,不是Windows专家。
一些链接:
无论如何,最重要的是你在平台/编译器ABI规范中寻找你的保证,而不是C标准。
答案 1 :(得分:4)
唯一可以确定的方法是查阅相关编译器的文档。但是,通常情况下,C结构布局(除了,如您所说,用于位域)是由您正在使用的环境的ABI描述定义的,C编译器将倾向于遵循原生ABI。
答案 2 :(得分:1)
不仅它不是保证,而且即使您使用相同的编译器,也可能由于构建中使用的不同编译器开关而存在差异,或者如果您使用相同编译器和相同开关的不同版本(发生在我工作的嵌入式编译器。)
你需要确保结构表示完全相同,使用开关,#pragmas,无论编译器给你什么。
我的建议 - 完全避免这样做。在函数中传递参数,而不是包含在结构中。
即使以这种简单的形式,如果你处理两个编译器,它也不是微不足道的。例如,您需要确保int占用相同的字节数。同样调用conevntion - 参数顺序 - 从左到右或从右到左 - 在编译器之间可能不同。