自引用结构声明

3
以下声明是有效的。
struct node
{
    int a;
    struct node *next;
};

然而,当我们定义以下内容时,会出现错误。
"error: field ‘next’ has incomplete type"

为什么会这样呢?
struct node
{
    int a;
    struct node next; /* Not a pointer */   
};

是的,我已经纠正了那个。 - Sumit Trehan
7个回答

2

结构体不能包含自身作为成员:

struct node
{
    int a;
    struct node next;
};

思考一下这个问题:如果可能的话,这种结构的大小是多少?struct node 包含 struct node next 作为成员,那么成员 next 也将包含类型为 struct node 的成员,如此循环往复...大小将会是无限的。


2
在"struct node"中,node是一个"结构标签"。在你编写它时,它会创建一个"不完整类型":一个在这一点上未声明但未定义的结构变量。在结构体的最终"};"之前,该类型尚不完整。
在C语言中,即使未完全定义,也可以通过使用指向该类型的指针引用不完整的类型。然而,您无法分配该类型的变量(实例),因为实际的结构定义尚未定义。(如果您熟悉C++中的抽象基类,则它与其完全相同。)
因此,当您编写时
struct node {
  int a;
  struct node *next;
};

struct node *next 的意思是“这里有一个指向结构体节点的指针,尽管我还不知道该类型如何定义”。但是你不能在同一类型的结构定义中声明类型为 struct node 的变量,因为你不能在创建之前使用它。


1
这与类/结构类型的前向声明相同:
struct node;

struct node* node_ptr; /* is valid */
struct node node_instance; /* is invalid */

struct node; 的基本含义是:嘿,有一个结构体在这个文件之外被定义。类型是有效的,可以使用指针,但你不能实例化该对象。

这是因为指针的大小已知并且特定于目标架构(例如32位或64位)。结构体的大小直到声明时才会知道。

当您完全声明了该类型时,就可以声明该类型的对象:

struct node {
  int a;
  struct node* b; /* this will work, but the size of struct is unknown yet */
}

struct node* node_ptr; /* this works always with full and forward declarations */
struct node node_object; /* now, the size of struct is known, so the instance may be created */

1
您的第二个声明将定义一个无限深嵌套的结构体,这是不可能的。

其实我的问题是,如果指针类型声明没有错误,为什么在声明结构时会出错? - Sumit Trehan
第一个声明是有效的,因为指针的大小是恒定的,无论所引用的结构体如何。另一方面,不可能有一个嵌套在自身中的结构体,因为结果结构将是无限大小的。 - Codor

0

应该是这样的:

struct node {
  int a;
  struct node *next;
};

这个可以运行,

但是

struct node {
  int a;
  struct node next;
};

编译器无法理解node成为递归结构,因此不知道为node分配多少内存。

然而,如果您使用指针,它会理解指针的大小等于要寻址的内存的大小,并因此保留该空间,而不管node是否是完整的结构体。


0

指针存储地址,结构体有结构。如果像结构体声明它将会是递归和无限的。如果像指针声明,它将引用其他某处的结构。


0
一个节点内有无限个节点?这有意义吗?“struct node”的大小会是多少?

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