我可以'扩展'C中的结构吗?

时间:2011-09-10 08:27:30

标签: c struct

typedef struct foo_s {
    int a;
} foo;

typedef struct bar_s {
    foo;
    int b;
} bar;

基本上我想做:

bar b;
b.a;

我知道如果我在bar中命名了foo结构,我可以做b.foo_name.a,但我不想这样做。

有什么办法吗?

这个问题得到了各种不同的答案,所以让我解释一下这个问题。我想这样做的原因是因为我有一个我需要适应我的情况的库,这意味着我无法修改原始的struct decleration。此外,我需要做的就是在结构的开头添加1项(为什么开始?因为我有一个'object'结构,它可以处理项目中的所有结构)。我可以像你提到的那样简单地嵌入结构,但它真的很烦人,因为所有引用都需要输入'variable-> image.location'那个'图像'。键入十亿种类型真的很烦人。

8 个答案:

答案 0 :(得分:25)

显然this feature has been added to C11,但是我无法访问最近年份的C编译器(> = GCC 4.6.2)。

typedef struct foo {
  int a;
} foo;

typedef struct bar {
  struct foo;
  int b;
} bar;

int main() {
  bar b;
  b.a = 42;
  b.b = 99;
  return 0;
}

答案 1 :(得分:9)

您可以使用指针,因为保证指向结构对象的指针指向其第一个成员。参见例如this article

#include <stdlib.h>
#include <stdio.h>

typedef struct foo_s {
    int a;
} foo;

typedef struct bar_s {
    foo super;
    int b;
} bar;

int fooGetA(foo *x) {
  return x->a;
}

void fooSetA(foo *x, int a) {
  x->a = a;
}

int main() {
  bar* derived = (bar*) calloc(1, sizeof(bar));
  fooSetA((foo*) derived, 5);
  derived->b = 3;
  printf("result: %d\n", fooGetA((foo*) derived));
  return 0;
}

答案 2 :(得分:7)

不可能以C的方式进行。但您可以在foo中模仿具有bar成员变量的继承。

typedef struct bar_s {
    foo obj;
    int b;
} bar;

bar b;
b.obj.a = 10;

答案 3 :(得分:2)

如果你的话

typedef struct foo_s {
    int a;
  } foo;

typedef struct bar_s {
 foo my_foo;
int b;
} bar;

所以你可以这样做:

bar b; b.my_foo.a = 3;

否则,由于sizeof(bar_s)对编译时间不利,因此无法在C中执行此操作。这不是一个好习惯,但你可以在bar_s中保存一个void * ptr;指针,另一个描述ptr类型的枚举,并按类型转换。

即:

typedef enum internalType{
  INTERNAL_TYPE_FOO = 0,
}internalType_t;

typedef struct bar_s {
 internalType_t ptrType;
 void* ptr;
int b;
} bar;

然后:

bar b;  foo f;
b.ptrType = INTERNAL_TYPE_FOO;
b.ptr = &f;

以及代码中的其他地方:

 if (b.ptrType == INTERNAL_TYPE_FOO) {
    foo* myFooPtr = (foo *)b.ptr;
 }

答案 4 :(得分:0)

您可以尝试使用继承:

struct foo_s
{
    int a;
};

struct bar_s: foo_a
{
    int b;
};

适用于C ++,不确定它是否适用于C。

答案 5 :(得分:0)

可以通过预处理器轻松完成:

创建名为base_foo.h的文件:

int foo;

然后简单地加入它:

typedef struct foo_s {
    #include "base_foo.h"
} foo;

typedef struct bar_s {
    #include "base_foo.h"
    int b;
} bar;

答案 6 :(得分:0)

匿名结构与具有无名字段的联合之间存在混淆。无名字段是Microsoft扩展程序。

struct known {
    struct /* anonymous */ {
        int anonymous;
    };
    int known;
};

匿名structunionstructunion,而没有tag name嵌入另一个struct或{{1 }}。它也不需要任何字段名称。

无名字段是Microsoft扩展,它允许在C中进行有限的继承。

union

至少在C11标准定义中,匿名struct A { int a; }; struct B { struct A: // nameless field int b; }; struct不是无名字段,而无名字段也不是匿名。

答案 7 :(得分:0)

这是没有 c 标志的最简单方法

#include <stdio.h>

#define foo_s struct { int a; }
typedef foo_s foo;

typedef struct bar_s {
    foo_s; // extends foo_s
    int b;
} bar;

int main(void)
{
    bar b = {
        .a = 1,
        .b = 2,
    };
    foo *f = (foo *)&b;

    printf("a: %d\n", f->a);

    return 0;
}
$ gcc inherit.c
$ ./a.out
a: 1