145

我写 C 的时间不长,所以我不确定我应该如何去做这些递归的事情......我希望每个单元格包含另一个单元格,但是我得到了一个错误“字段‘孩子’的类型不完整”的行。这是怎么回事?

typedef struct Cell {
  int isParent;
  Cell child;
} Cell;
4

9 回答 9

202

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

然而一个CellCAN 包含一个指向另一个的指针Cell

typedef struct Cell {
  bool isParent;
  struct Cell* child;
} Cell;
于 2009-02-26T00:52:27.230 回答
34

在 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;
}

尽管在标准中它可能比这复杂得多,但您可以将其视为编译器struct Cell在第一行typedef知道但tCell直到最后一行才知道:-) 这就是我记住该规则的方式。

于 2009-02-26T01:27:11.157 回答
14

从理论的角度来看,语言只能支持自指结构,不能支持自包含结构。

于 2009-07-29T19:13:40.523 回答
13

有一种解决方法:

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

struct Cell;
typedef struct Cell Cell;

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

于 2009-07-29T19:05:30.310 回答
7

我知道这篇文章很旧,但是,为了获得您正在寻找的效果,您可能想尝试以下方法:

#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 *”。

于 2012-03-24T01:47:42.617 回答
5

另一种方便的方法是使用结构标记预先定义结构为:

//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;
于 2016-05-24T18:43:17.337 回答
3

让我们看一下 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。

于 2014-12-23T10:19:30.910 回答
1

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

struct node
{
       int data;
       struct node *next; // <-self reference
};
于 2010-10-24T13:10:23.137 回答
1

以前的所有答案都很棒,我只是想深入了解为什么结构不能包含其自身类型的实例(不是参考)。

非常重要的是要注意结构是“值”类型,即它们包含实际值,因此当您声明一个结构时,编译器必须决定为它的实例分配多少内存,因此它会遍历其所有成员并添加增加他们的内存来计算结构的全部内存,但是如果编译器在内部找到相同结构的实例,那么这是一个悖论(即,为了知道结构 A 需要多少内存,您必须决定多少内存结构 A 需要!)。

但是引用类型是不同的,如果一个结构'A'包含一个对它自己类型的实例的'引用',虽然我们还不知道分配了多少内存,但我们知道分配了多少内存给内存地址(即参考)。

高温高压

于 2016-12-11T17:28:27.770 回答