C 与 C++ 结构对齐

C vs C++ struct alignment

我在最近的一次采访中被问到有关 C++ 结构字段对齐的问题,并且从理论上讲,C 和 C++ 在结构打包方面遵循相同的策略。

然而,这是错误的假设。面试官说,通常 C 和 C++ 以不同的方式打包结构,我们永远不应该期望相反的情况。恕我直言,这是一个奇怪的说法。在双语 C/C++ 头文件中使用 C++ 中的结构没有 pack "C" 限定符。

所以在实践中,这可能意味着您不能在 C++ 中创建结构并将其传递给 C 库,因为通常它的字段将以不同的方式对齐并具有不同的偏移量。但是,事实上,大多数程序员严重依赖这种互操作性,直到他们使用一些辅助方法将指向 C POD 结构的指针转换为对该结构周围的 C++ 包装器的引用。你能澄清一下吗?

这显然是错误的(在面试官方面)。很明显,对于任何使用任何低级别 API 处理结构的人来说,结构打包对于 C 和 C++ 都是相同的——例如,网络 API。所有这些都是 C 函数,它们接受 'C' 结构,但每天从 C++ 代码中安全地调用它们数百万次。

你应该很幸运你有这个问题。它清楚地表明你不应该在那里工作。

C 和 C++ 语言标准都没有对结构填充提出要求,将其留给编译器实现细节。对此的严格解释意味着不能保证两者之间的结构相同。

然而,实际上,如果需要,能够同时支持 C 和 C++ 的给定版本的工具链(例如 GCC 或 Clang)可以以相同的方式打包相同的结构。没有这个,世界上很多生产代码根本无法工作。然而,这是工具链提供的保证,不是语言。

值得注意的是,如果您要声明与 C 原始结构类似的结构,但添加了访问说明符(privatepublicprotected),那么布局会改变,但这有点牵强,因为结构不再相同。

开发 C++ 时,开发人员发现 C 程序员依赖于一些 C++ 开发人员不想保证的东西,但不保证它们意味着很多 C 代码也是有效的 C++ 代码当用作 C++ 代码时会被破坏。不可取。

这就是他们发明 "POD" 结构的原因:不使用任何 C++ 功能的结构在 C++ 程序中的行为与在 C 程序中的行为完全相同(除了实现定义的行为可能改变,因为 C 编译器和 C++ 编译器显然不是相同的实现。另一方面,C++ 编译器可能只是从 C 编译器复制实现定义)。

如果您采用任何也是有效 C++ 结构的普通 C 结构(例如,没有名为 "class" 的成员),然后您只需在左大括号之后添加 "public:",那么它的布局、成员顺序、对齐方式等都可以更改。尽管默认情况下所有结构成员都是 public,但实际上没有任何改变。除了因为 "public:" 它不再是 POD。