64

在最近的一次采访中,有人问我关于 C++ 结构字段对齐的问题,并认为 C 和 C++ 在结构打包中遵循相同的策略。

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

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

4

3 回答 3

69

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

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

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

于 2015-11-20T20:46:42.907 回答
29

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

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

于 2015-11-20T20:44:54.250 回答
4

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

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

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

于 2015-11-21T19:38:31.463 回答