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

时间:2012-04-24 12:46:47

标签: c windows portability

假设以下头文件对应于(例如)共享库。导出的函数获取指向此标头中定义的自定义结构的指针:

// 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),但也很想了解其他平台。

3 个答案:

答案 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 - 参数顺序 - 从左到右或从右到左 - 在编译器之间可能不同。

相关问题