2009-05-20 95 views
28

在typedef这些结构中解决下列循环依赖的最佳方法是什么?
注C语言的标签 - 我希望在标准的gcc C的解决方案解决循环typedef依赖性?

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

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

回答

27

前向申报结构之一:


struct people; 

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

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

有人应该提到你必须写typedef struct people {....}人;然后。所以,它与以前不完全一样(imho,无论如何给出明确的标签名称是个好主意) – 2009-05-21 00:45:51

+0

你是对的,是懒得回去编辑答案,现在就去做。 – 2009-05-21 01:11:22

+1

在struct Person不能声明`struct people friends`而不是指针吗?它给我带来了错误。例如:`struct people;``typedef struct {struct people friends;} Person;`和`typedef struct people {Person person;};` – 2016-10-05 09:22:42

1

由于Person只是想要一个指向People,应该没事,只是预先声明后:

typedef struct People People; 

然后更改第二个声明,只是声明使用结构标签,就像这样:

struct People { 
    int count; 
    int max; 
    Person data[]; 
}; 
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; 
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

至于可读性:

typedef struct Foo_ Foo; 
typedef struct Bar_ Bar; 

struct Foo_ { 
    Bar *bar; 
}; 

struct Bar_ { 
    Foo *foo; 
}; 

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

35

答案在于声明和定义的区别。您试图在同一步骤中声明和定义(在使用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类型。所以下面也将工作,但不推荐,因为它是脆弱的:

typedef struct People People; 

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

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

如果交换结构定义(移动中的人的类型定义上述结构的人),它会再次失败的顺序。这是什么让这个脆弱,因此,不建议。

请注意,如果您包含指定类型的结构而不是指向它的指针,则此技巧无效。因此,举例来说,下面的不会编译

typedef struct Bar Bar; 

struct Foo 
{ 
    Bar bar; 
}; 

struct Bar 
{ 
    int i; 
}; 

上面的代码提供了一个编译器错误,因为该类型的酒吧是不完整的,当它试图使用它结构foo的定义中。换句话说,它不知道分配给结构成员'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圆形指针,因为类型“富”和“酒吧”已预先宣布(但尚未定义),因此编译器可以构建一个指向它们的指针。当我们开始定义FooBar时,我们已经定义了Foo和Bar的大小,因此我们可以在其中包含实际对象。我们还可以包含一个指向FooBar类型的自指针指针,因为我们已经预先声明了类型。

请注意,如果您将struct FooBar的定义移到了struct Foo或Bar的定义之上,那么它将不会与前面的示例(不完整类型)相同的原因进行编译。