这个代码是否由C标准保证?

我已经读过如果你声明这样的两个结构:

struct Node { int a, b, c; }; struct DerivedNode { struct Node base; int d, e, f; }; 

然后你可以像这样使用指针:

 struct DerivedNode myDerivedNode; struct Node *regularNode = (struct Node *) &myDerivedNode; regularNode->a = 3; 

换句话说, a, b, c的地址偏移在struct Nodestruct DerivedNode中是相同的。 因此,您可以从中获得一种多态性,您可以在其中传递强制(struct Node *) cast DerivedNode指针,无论何时通常采用Node指针。

我的问题是这种行为是否得到保证。 我知道有一些奇怪的内存对齐问题,编译器有时会重新排序字段以实现更好的内存打包。 base字段是否会位于struct DerivedNode的开头?

这保证符合标准。 结构中的成员按指定的顺序按顺序排列,第一个成员始终显示在偏移0处。

ANSI C标准的相关摘录:

结构是由一系列成员组成的类型,其存储以有序序列分配。

这表明成员按顺序排列。

结构对象中可能存在未命名的填充,但不是在其开头。

意味着第一个成员位于偏移0处。

注:标准摘录摘自ISO / IEC 9899:TC3 2007年9月草案第6.7.2.1节。

正如大卫所说,只要base仍然是DerivedNode的第一个元素, DerivedNode

但通常这是不好的做法。 我无法弄清楚你不能说的很多情况

 struct Node *regularNode = &myDerivNode.base; 

如果您稍后修改结构,这将更清晰,更不容易出错。

这不会回答你的问题,但是一个关心编写标准ANSI(ISO)C的人可以用gcc -pedantic-pedantic-errors编译他的代码。 这些选项应该会在非标准代码行上引发编译警告/错误。

请注意,这不是100%有效,来自man gcc

[-pedantic]发现了一些非ISO实践,但并非全部 – 只有那些ISO C 需要诊断的实践,以及其他一些已经添加了诊断的实践。