此C继承实现是否包含未定义的行为?

时间:2017-01-25 17:58:01

标签: c struct language-lawyer

struct parent
{
    char a;
    char b;
};

struct child
{
    struct parent parent;
    int c;
    char d;
};

struct grandchild
{
    struct child child;
    long e;
};

void print_parent_val(struct parent *p)
{
    printf("%d\n", p->a);
}

int main (int argc, char **argv)
{
    struct grandchild g;
    g.child.parent.a = 69;
    print_parent_val((struct parent *)&g);
    return 0;
}

程序编译(没有警告)并运行正常并按预期打印69。我从未见过任何实现这种继承技术的代码,因此我非常犹豫地将其视为" OK"。

编辑:如何将孙子变成一个孩子?中期转换也有可能吗?

void print_parent_val(struct child *c)
{
    printf("%c\n", c->d);
}

int main (int argc, char **argv)
{
    struct grandchild g;
    g.child.parent.a = 69;
    g.child.d = 'w';
    print_parent_val((struct child *)&g);
    return 0;
}

1 个答案:

答案 0 :(得分:7)

正如我所看到的,这里没有未定义行为的范围

引用C11,章节§6.7.2.1,结构和联合说明符,(强调我的

  

在结构对象内,非位字段成员和位域中的单位   驻留的地址按声明的顺序增加。 指向a的指针   结构对象,适当转换,指向其初始成员(或者如果该成员是   位字段,然后到它所在的单元,反之亦然。 可能有未命名的   在结构对象中填充,但不在其开头。

所以,使用当前的片段(和方法),你应该好好去。