我已经读过,如果你声明这样的两个结构:
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 *)
- 演员DerivedNode指针,无论在哪里通常都会采用Node指针。
我的问题是这种行为是否得到保证。我知道有一些奇怪的内存对齐问题,编译器有时会重新排序字段以实现更好的内存打包。 base
字段是否会位于struct DerivedNode
的开头?
答案 0 :(得分:13)
这保证符合标准。结构中的成员按照您指定的顺序按顺序排列,第一个成员始终显示在偏移0处。
ANSI C标准的相关摘录:
结构是由一系列成员组成的类型,其存储按有序顺序分配。
这说明成员按顺序排列。
结构对象中可能有未命名的填充,但不在其开头。
表示第一个成员位于偏移0处。
注:标准摘录摘自ISO / IEC 9899:TC3 2007年9月草案第6.7.2.1节。
答案 1 :(得分:3)
正如大卫所述,只要base
仍然是DerivedNode
中的第一个元素,就可以保证这一点。
但通常这是不好的做法。我无法弄清楚你不能说的很多情况
struct Node *regularNode = &myDerivNode.base;
如果您稍后修改结构,则更清晰,更不容易出错。
答案 2 :(得分:1)
这不会回答你的问题,但是一个关心编写标准ANSI(ISO)C的人可以用gcc -pedantic
或-pedantic-errors
编译他的代码。这些选项应该在非标准代码行上引发编译警告/错误。
请注意,这不是100%有效,来自man gcc
:
[ - pedantic]发现了一些非ISO实践,但不是全部 - 只有那些 哪个ISO C 需要诊断,以及其他一些诊断 诊断已被添加。