Bar的第一个成员是Foo结构,对Bar的任何引用也是对Foo的有效引用

时间:2018-12-24 10:52:44

标签: c pointers types casting

标题中的陈述在哪种情况下是正确的?哪个版本的C以及哪个编译器选项?

我的问题源自史蒂夫的陈述: “您现在应该注意到-因为我们的FooSubclass的第一个成员实际上是Foo结构-任何对FooSubclass的引用也是对Foo的有效引用-意味着它几乎可以在任何地方使用。”({ {3}})这是我第一次看到有人提到这种事情。以下代码会发出警告,因此我对此声明的有效性提出疑问。

#include <stdio.h>
#include <assert.h>

typedef struct Foo {
    int weight;
} Foo;

Foo foo_init(int weight) {
    Foo t;
    t.weight = weight;
    return t;
}

int foo_weight(const Foo *this) {
    return this->weight;
}

typedef struct Bar {
    Foo base;
    int size;
} Bar;

Bar bar_init(int weight, int size) {
    Bar w;
    w.base = foo_init(weight);
    w.size = size;
    return w;
}

int bar_weight(const Bar *this) {
    return foo_weight(this);
}

int bar_size(const Bar *this) {
    return this->size;
}

int main (int argc, char *argv[]) {
    Foo t = foo_init(22);
    Bar w = bar_init(20,14);

    assert(foo_weight(&t) == 22);
    assert(bar_weight(&w) == 20);
    assert(bar_size(&w) == 14);

    return 0;
}

结果:

> gcc main.c

main.c: In function 'bar_weight':
main.c:31:20: warning: passing argument 1 of 'foo_weight' from incompatible pointer type [-Wincompatible-pointer-types]
 return foo_weight(this);
                ^~~~
main.c:14:5: note: expected 'const Foo * {aka const struct Foo *}' but argument is of type 'const Bar * {aka const struct Bar *}'
 int foo_weight(const Foo *this) {

1 个答案:

答案 0 :(得分:2)

  

标题中的陈述在哪种情况下是正确的?

无条件。正确的说法是“ Bar的第一个成员是Foo结构,可以将对Bar的任何引用投射为对Foo的有效引用”。

这在6.7.2.1p15的C标准中有记录:

  

6.7.2.1结构和联合说明符

     

5指向经过适当转换的结构对象的指针指向   它的初始成员(如果该成员是位字段,则为该单元   它所在的位置),反之亦然。可能有未命名的填充   在结构对象中,而不是在结构对象的开头。

自从C的概念出现以来就是如此。