解决循环typedef依赖?

时间:2009-05-20 14:46:29

标签: c circular-dependency

在typedef-ing这些结构中解决以下循环依赖的最佳方法是什么? 注意C语言标记 - 我正在寻找标准gcc C中的解决方案。

typedef struct {
    char* name;
    int age;
    int lefthanded;
    People* friends;
} Person;

typedef struct {
    int count;
    int max;
    Person* data;
} People;

6 个答案:

答案 0 :(得分:42)

答案在于声明和定义之间的区别。您试图在同一步骤中声明和定义(在通过typedef的新类型的情况下)。您需要将它们分解为不同的步骤,以便编译器事先知道您在说什么。

typedef struct Person Person;
typedef struct People People;

struct Person {
    char* name;
    int age;
    int lefthanded;
    People* friends;
};

struct People {
    int count;
    int max;
    Person* data;
};

注意在顶部添加了两个“空”typedef(声明)。这告诉编译器新类型Person的类型为'struct Person',这样当它在struct People的定义中看到它时,它知道它意味着什么。

在您的特定情况下,您实际上只能预先解析People typdef,因为这是在定义之前使用的唯一类型。当您进入struct People的定义时,您已经完全定义了Person类型。所以以下内容也可以,但 NOT WOMMENDED 因为它很脆弱:

typedef struct People People;

typedef struct {
    char* name;
    int age;
    int lefthanded;
    People* friends;
} Person;

struct People {
    int count;
    int max;
    Person* data;
};

如果交换结构定义的顺序(在Person的typedef之上移动struct People),它将再次失败。这就是使这个脆弱的原因,因此,不推荐。

请注意,如果包含指定类型的结构而不是指向它的指针,则此技巧不起作用。因此,例如,以下将无法编译

typedef struct Bar Bar;

struct Foo
{
    Bar bar;
};

struct Bar
{
    int i;
};

上面的代码给出了编译器错误,因为当它尝试在struct Foo的定义中使用它时类型Bar是不完整的。换句话说,它不知道分配给结构成员'bar'的空间有多大,因为它还没有看到struct bar的定义。

此代码将编译

typedef struct Foo Foo;
typedef struct Bar Bar;
typedef struct FooBar FooBar;

struct Foo
{
    Bar *bar;
};

struct Bar
{
    Foo *foo;
};

struct FooBar
{
    Foo     foo;
    Bar     bar;
    FooBar  *foobar;
};

即使使用Foo和Bar中的循环指针,这也有效,因为类型'Foo'和'Bar'已经预先声明(但尚未定义),因此编译器可以构建指向它们的指针。

当我们定义FooBar时,我们已经定义了Foo和Bar的大小,因此我们可以在那里包含实际对象。我们还可以包含一个指向FooBar类型的自引用指针,因为我们已经预先声明了类型。

请注意,如果您将struct FooBar的定义移到struct Foo或Bar的定义之上,则它将无法编译,原因与前一个示例相同(不完整类型)。

答案 1 :(得分:28)

转发声明其中一个结构:


struct people;

typedef struct {
  /* same as before */
  struct people* friends;
} Person;

typedef struct people {
  /* same as before */
} People;

答案 2 :(得分:5)

至于可读性:

typedef struct Foo_ Foo;
typedef struct Bar_ Bar;

struct Foo_ {
    Bar *bar;
};

struct Bar_ {
    Foo *foo;
};

完全避免typedef struct可能是个好主意;

答案 3 :(得分:2)

由于Person只需要一个指向People的指针,因此只需预先确定后者即可:

typedef struct People People;

然后将第二个声明更改为仅使用struct标签声明,如下所示:

struct People {
    int count;
    int max;
    Person data[];
};

答案 4 :(得分:1)

struct _People;

typedef struct {
    char* name;
    int age;
    int lefthanded;
    struct _People* friends;
} Person;

struct _People {
    int count;
    int max;
    Person data[1];
};

注意:Person data[];标准吗?

答案 5 :(得分:0)

struct People_struct;

typedef struct {
    char* name;
    int age;
    int lefthanded;
    struct People_struct* friends;
} Person;

typedef struct People_struct {
    int count;
    int max;
    Person data[];
} People;