答案在于声明和定义的区别。您试图在同一步骤中声明和定义(在使用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的定义之上,那么它将不会与前面的示例(不完整类型)相同的原因进行编译。
有人应该提到你必须写typedef struct people {....}人;然后。所以,它与以前不完全一样(imho,无论如何给出明确的标签名称是个好主意) – 2009-05-21 00:45:51
你是对的,是懒得回去编辑答案,现在就去做。 – 2009-05-21 01:11:22
在struct Person不能声明`struct people friends`而不是指针吗?它给我带来了错误。例如:`struct people;``typedef struct {struct people friends;} Person;`和`typedef struct people {Person person;};` – 2016-10-05 09:22:42