自引用结构定义?

我写 C 的时间不长,所以我不确定我应该如何做这些递归的事情... ... 我希望每个单元格包含另一个单元格,但是我得到了一个错误,类似于“ field‘ child’has not type”。怎么了?

typedef struct Cell {
int isParent;
Cell child;
} Cell;
136235 次浏览

显然,一个 Cell不能包含另一个 Cell,因为它变成了一个永无止境的递归。

但是,Cell可以包含指向另一个 Cell的指针。

typedef struct Cell {
bool isParent;
struct Cell* child;
} Cell;

在 C 语言中,不能引用用结构本身创建的 typedef。必须使用结构名称,如下面的测试程序所示:

#include <stdio.h>
#include <stdlib.h>


typedef struct Cell {
int cellSeq;
struct Cell* next; /* 'tCell *next' will not work here */
} tCell;


int main(void) {
int i;
tCell *curr;
tCell *first;
tCell *last;


/* Construct linked list, 100 down to 80. */


first = malloc (sizeof (tCell));
last = first;
first->cellSeq = 100;
first->next = NULL;
for (i = 0; i < 20; i++) {
curr = malloc (sizeof (tCell));
curr->cellSeq = last->cellSeq - 1;
curr->next = NULL;
last->next = curr;
last = curr;
}


/* Walk the list, printing sequence numbers. */


curr = first;
while (curr != NULL) {
printf ("Sequence = %d\n", curr->cellSeq);
curr = curr->next;
}


return 0;
}

尽管在标准中它可能比这复杂得多,你可以把它看作是编译器在 typedef的第一行知道 struct Cell,但是直到最后一行才知道 tCell: ——)这就是我如何记住这条规则的。

有一种方法可以解决这个问题:

struct Cell {
bool isParent;
struct Cell* child;
};


struct Cell;
typedef struct Cell Cell;

如果您像这样声明它,它会正确地告诉编译器 struct Cell 和 platleol’-Cell 是相同的。所以你可以像平常一样使用 Cell。但是仍然必须在初始声明本身内部使用 struct Cell。

从理论上看,语言只能支持自指结构,而不能支持自包结构。

包含对自身的引用的结构。这种情况在描述链接列表节点的结构中很常见。每个节点都需要引用链中的下一个节点。

struct node
{
int data;
struct node *next; // <-self reference
};

我知道这篇文章很老了,但是,为了达到你想要的效果,你可以尝试下面的方法:

#define TAKE_ADVANTAGE


/* Forward declaration of "struct Cell" as type Cell. */
typedef struct Cell Cell;


#ifdef TAKE_ADVANTAGE
/*
Define Cell structure taking advantage of forward declaration.
*/
struct Cell
{
int isParent;
Cell *child;
};


#else


/*
Or...you could define it as other posters have mentioned without taking
advantage of the forward declaration.
*/
struct Cell
{
int isParent;
struct Cell *child;
};


#endif


/*
Some code here...
*/


/* Use the Cell type. */
Cell newCell;

在上面的代码片段中提到的两种情况中的任何一种,您必须将子 Cell 结构声明为指针。如果您没有,那么您将得到“字段‘ child’具有不完整的类型”错误。原因是必须定义“ struct Cell”,以便编译器知道在使用它时要分配多少空间。

如果您试图在“ struct Cell”的定义中使用“ struct Cell”,那么编译器还不知道“ struct Cell”应该占用多少空间。然而,编译器已经知道一个指针占用多少空间,并且(通过前向声明)它知道“ Cell”是一种“ struct Cell”类型(尽管它还不知道“ struct Cell”有多大)。因此,编译器可以在正在定义的结构中定义一个“ Cell *”。

让我们来看一下 typedef 的基本定义。Typedef 用于为用户定义或内置的现有数据类型定义别名。

typedef <data_type> <alias>;

比如说

typedef int scores;


scores team1 = 99;

这里与自引用结构相混淆,原因是同一数据类型的成员没有在前面定义。因此,按照标准方式,您可以将代码编写为:-

//View 1
typedef struct{ bool isParent; struct Cell* child;} Cell;


//View 2
typedef struct{
bool isParent;
struct Cell* child;
} Cell;


//Other Available ways, define stucture and create typedef
struct Cell {
bool isParent;
struct Cell* child;
};


typedef struct Cell Cell;

但是最后一个选项增加了一些额外的行和词,通常是我们不想做的(我们太懒了,你知道的;)。所以更喜欢视图2。

另一种方便的方法是预先类型化结构,其结构标签如下:

//declare new type 'Node', as same as struct tag
typedef struct Node Node;
//struct with structure tag 'Node'
struct Node
{
int data;
//pointer to structure with custom type as same as struct tag
Node *nextNode;
};
//another pointer of custom type 'Node', same as struct tag
Node *node;

以前的答案都很棒,我只是想深入了解一下为什么一个结构不能包含它自己类型的实例(而不是引用)。

值得注意的是,结构是“值”类型,即它们包含实际的值,所以当你声明一个结构时,编译器必须决定分配给它的一个实例多少内存,所以它通过所有的成员并加上它们的内存来计算结构的整体内存,但是如果编译器发现一个相同的结构的实例在里面,那么这是一个悖论(即为了知道多少内存结构 A 需要你必须决定多少内存结构 A 需要.

但是引用类型是不同的,如果一个结构“ A”包含一个对它自己类型的实例的“引用”,尽管我们还不知道有多少内存被分配给它,但我们知道有多少内存被分配给一个内存地址(即引用)。

高温