【发布时间】:2019-08-28 19:59:16
【问题描述】:
我正在 C89 中实现一棵二叉树,并且我试图通过组合在所有节点结构之间共享公共属性。因此我有以下代码:
enum foo_type
{
FOO_TYPE_A,
FOO_TYPE_B
};
struct foo {
enum foo_type type;
};
struct foo_type_a {
struct foo base;
struct foo * ptr;
};
struct foo_type_b {
struct foo base;
char * text;
};
我在所有结构定义中都包含一个struct foo 类型的成员作为它们的初始成员,以便提供对enum foo_type 持有的值的访问,而不管结构类型如何。为了实现这一点,我期望一个指向结构对象的指针指向它的初始成员,但我不确定这个假设在这种情况下是否成立。对于 C99,标准规定如下(参见 ISO/IEC 9899:1999 6.7.2.1 §13)
一个指向结构对象的指针,经过适当的转换,指向它的初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。结构对象中可能有未命名的填充,但不是在其开头。
虽然所有结构都共享一个共同的 struct foo 对象作为它们的初始成员,但填充开始发挥作用。虽然struct foo 只有一个成员,大小与int 相同,但struct foo_type_a 和struct foo_type_b 都包含指针成员,这在某些情况下会增加对齐并因此增加填充。
因此,考虑到这种情况,C 编程语言(C89 或任何后续版本)是否确保通过指向对象的指针访问 struct foo::type 的值是安全的,无论该对象的类型是 struct foo 还是包含struct foo 类型的对象作为其第一个成员,例如struct foo_type_a 或struct foo_type_b?
【问题讨论】:
-
struct foo总是相同,无论它是在另一个结构中还是单独存在。其他结构成员不能使struct foo的两个实例在内存中具有不同的布局 -
@n.m.:不需要更多代码。很明显,他们想知道 C 1989 是否保证将指向结构的指针转换为指向其第一个成员类型的指针会产生指向其第一个成员的指针。
-
我不得不问,你为什么要在 1989 C 中开发新代码?
-
是的。引用的保证以及所有
pointer-to-struct类型应具有相同表示的保证是conformant 类型别名的基础。见What is the strict aliasing rule? -
@UnholySheep 我担心的是 C 标准还指出对象需要“适当转换”的警告,我不确定指针类型之间的简单转换是否代表合适的转换。例如,如果对齐从 4 增加到 8 并且字节顺序魔法移动了重要位,那么天真的强制转换可能会导致问题。
标签: c memory-alignment c89 packing