【问题标题】:C struct alignment and portability across compilers跨编译器的 C 结构对齐和可移植性
【发布时间】:2012-05-05 02:26:24
【问题描述】:

假设下面的头文件对应,例如一个共享库。导出的函数采用指向此标头中定义的自定义结构的指针:

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

【问题讨论】:

  • 不,除非有人向你保证。
  • 无重复。至少不是选择的问题。这个可以独立站立。
  • 任何包含“结构对齐”字样的问题是否会自动与其他问题重复,即使它与它无关?...
  • 建议的副本实际上回答了问题“是否保证结构内存对齐方式相同?” 就好了。不能保证,因为 c 标准允许每个编译器做出自己的选择。如果这里的主要问题是“我如何确保我的结构定义在同一平台上的不同编译器之间是可移植的?” 它应该更加突出。您应该尝试阅读相关编译器的文档。
  • @dmckee,感谢您的意见,我稍微改写了这个问题。

标签: c windows portability


【解决方案1】:

TL;DR 在实践中应该没问题。

C 标准没有定义这一点,但平台 ABI 通常会定义。也就是说,对于给定的 CPU 架构和操作系统,可以定义 C 如何映射到允许不同编译器互操作的程序集。

结构对齐并不是平台 ABI 必须定义的唯一内容,您还有函数调用约定和类似的东西。

C++ 让它变得更加复杂,ABI 必须指定 vtable、异常、名称修改等。

在 Windows 上,我认为有多个 C++ ABI,具体取决于编译器,但 C 大多在编译器之间兼容。我可能是错的,不是 Windows 专家。

一些链接:

无论如何,底线是您在平台/编译器 ABI 规范中寻找保证,而不是 C 标准。

【讨论】:

  • 感谢您的努力,尽管我的问题根本与 C++ 无关。我了解 ABI,这也是我将问题标记为 Windows-specific 的原因,因为我从未听说过 Windows 上的 ABI 规范。
  • @7vies:C 也有 ABI(想想不同的调用约定,cdecl、stdcall、fastcall)。只是对于 C,不同的编译器通常是相同的(至少对于“正常”调用约定),如果没有其他原因,只是为了匹配操作系统对系统调用的期望。对于 C++,不同的编译器通常同意相同的 API,尤其是对于外部名称。
  • @MichaelBurr,作为旁注,维基百科说这些是 x86 约定,它们是否也用于其他架构?我知道 C++ 的问题,这就是为什么我要问如何使它在纯 C 中工作。调用约定确实有助于定义可移植接口,但不能解决我的结构对齐问题。
  • @7vies:每个平台都有自己的调用约定/ABI(尽管它们可能会相互影响;Itanium ABI 似乎影响了几个 64 位平台 ABI)。我刚刚列出了 x86 的例子,作为 C 语言如何拥有 ABI 的例子。我认为 Havoc 的答案几乎就是你所拥有的 - C 标准没有任何承诺,但平台要求会做到这一点,因此在实践中,只要你不这样做,编译器的结构对齐(C++ 的 POD 结构)将是相同的乱用古怪的类型(比如long long double)或滥用影响对齐的选项。
【解决方案2】:

唯一确定的方法是查阅相关编译器的文档。但是,通常情况下,C 结构布局(如您所说,位域除外)由您正在使用的环境的 ABI 描述定义,C 编译器将倾向于遵循本机 ABI。

【讨论】:

    【解决方案3】:

    不仅没有保证,而且即使您使用相同的编译器,由于构建中使用的编译器开关不同,或者如果您使用相同编译器和相同开关的不同版本(发生在我工作的嵌入式编译器)。

    您需要确保结构的表示完全相同,使用开关、#pragmas,无论编译器为您提供什么。

    我的建议 - 完全避免这种情况。在函数中传递参数,而不是包装在结构中。

    即使在这种简单的形式中,如果您处理两个编译器,这也不是微不足道的。例如,您需要确保 int 采用相同数量的字节。还调用 conevntion - 参数顺序 - 从左到右或从右到左 - 编译器之间可能会有所不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2017-07-15
      • 2010-10-07
      相关资源
      最近更新 更多