我正在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:19996.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
?
正如您自己引用C标准所述,C99及更高版本支持您所描述的内容。
看来它也得到C89的支持,因为你引用的语言已经出现在1988年的ANSI-C文件中:
3.5.2.1结构和联合说明符
...
在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址。指向结构对象的指针(适当地强制转换)指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。因此,在结构对象中可能存在未命名的孔,但不是在其开始处,以实现适当的对齐。