结构体内部的结构体

17

我需要创建一个人,每个人都应该有一台冰箱。这是最好的方法吗?如果是,那么我做错了什么?提前感谢。

typedef struct {
 int age;
 struct FRIDGE fridge;
} PERSON;

typedef struct {
 int number;
} FRIDGE;

FRIDGE fr;
fr.number=1;

PERSON me;
me.name=1;
me.fridge = fr;

这给我带来了以下错误:

错误:字段“fridge”的类型不完整


2
你正在使用匿名结构体,因此不应该使用 struct 关键字,而是使用 typedef 命名的名称。请将 struct FRIDGE fridge 更改为 FRIDGE fridge - manav m-n
3
@Manav:在问题中编辑代码是错误的回答方式。只需编辑问题代码以修复可怜的格式,例如错误的缩进。 - Ben Voigt
1
@BenVoigt:+1 点已注意!!! - manav m-n
4个回答

25

struct FRIDGEFRIDGE是两个不同的东西。

你需要在其他结构中使用类型FRIDGE

typedef struct {
 int age;
 FRIDGE fridge;
} PERSON;

或者将您的冰箱定义为结构体FRIDGE

struct FRIDGE {
 int number;
};

此外,在使用结构体之前可能需要定义它的结构(例如,在人物上方)。


4

在清除所有警告和错误之后,您必须使用FRIDGE的成员。在声明PERSON之前声明FRIDGE

me.fridge.number = 1

编辑:我发现了错误。您正在使用匿名结构体,因此不应使用struct关键字,而应使用typedef定义的名称。

struct FRIDGE fridge更改为FRIDGE fridge


这不是问题,现代C语言方言支持结构的直接赋值。请查看错误信息。 - che
如果你对FRIDGE进行前向声明,错误就会消失。除非像memset一样做某些事情,否则最好为结构成员分配值而不是整个结构。这可以避免在将来添加更多结构成员时出现错误。 - manav m-n
好的,这就是原始代码在做什么。您已经使用成员初始化了 fr,然后只是将结构放入另一个结构中。如果添加更多成员,则不会出现任何错误。(另外,有时候当基础结构被扩展时,我希望我的代码能够失败。这可能是一种有用的提醒,以添加缺少的初始化。) - che
@che:当你声明 struct A { struct B xyz;}; 时,前面一行应该是 struct B; 或者是 struct B 的完整定义。否则编译器如何计算 struct B 的大小并知道为最终的 struct A 分配多少内存呢? - manav m-n
好的,那我们试一下,在声明PERSON之前声明FRIDGE,并使用它的成员:https://gist.github.com/4380192 - che
显示剩余2条评论

2
使用typedef与您的结构体会让您陷入这种混乱中。在struct标识符前面放置struct关键字是结构体应该使用的方式,这也更具显式性和易读性。
这里有一篇详细的博客文章,其中包含所有细节: https://www.microforum.cc/blogs/entry/21-how-to-struct-lessons-on-structures-in-c/ 但简单来说,您真正想做的是像这样省略typedef:
struct FRIDGE;  // This is a forward declaration, now an incomplete type

struct PERSON{
 int age;
 struct FRIDGE fridge;
};

struct FRIDGE{
 int number;
};

struct FRIDGE fr;
fr.number=1;

struct PERSON me;
me.name=1;
me.fridge = fr;

Linus Torvalds曾经也谈到过这个问题,他有非常充分的理由说明在所有结构体中使用typedef是令人困惑和不好的。

https://yarchive.net/comp/linux/typedefs.html

注: "Original Answer" 翻译成中文为“最初的回答”。

1

要么提前声明struct FRIDGE;

或者,在结构体PERSON中使用之前,先给FRIDGE定义。


1
代码确实包含了前向声明。但是在这里,仅有前向声明是不够的,需要完整的定义才能嵌入一个实例(而不是指针)。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接