这个代码是否由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 Node
和struct 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 需要诊断的实践,以及其他一些已经添加了诊断的实践。