我没有写很长时间的C语言,所以我不确定我应该如何处理这些递归问题... 我想每个单元格都包含另一个单元格,但我得到了类似于“字段'child'具有不完整的类型”的错误。怎么回事?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
很明显,一个 Cell
不能包含另一个 Cell
,否则它会变成无限递归。
然而,一个 Cell
可以包含指向另一个 Cell
的指针。
typedef struct Cell {
bool isParent;
struct Cell* child;
} Cell;
Cell
目前不在范围内。 - fredoverflowCell*
赋值给cell->child
时,我会收到警告。 - Tomáš Zato在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和plain-ol'-cell是相同的。因此,你可以像正常情况下一样使用Cell。不过,在初始声明本身内仍然必须使用struct Cell。
struct Cell;
? - MAKZstruct Cell;
多余。 但是,如果出于某种原因将最后两行放入头文件中,并在定义第一四行的 Cell
结构之前包含该头文件,则需要额外的 struct Cell;
。 - yynytypedef struct Cell Cell;
,它会将Cell
作为struct Cell
的别名。编译器是否之前看到过struct Cell { .... }
并不重要。 - melpomene//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;
我知道这篇文章有些陈旧了,但是如果你想要达到你想要的效果,可以尝试以下方法:
#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;
让我们先了解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;
但是最后一种选项会增加一些额外的行和单词,通常我们不想这样做(你知道我们很懒 ;))。所以更喜欢第二种视图。
typedef
语法的解释是错误的(考虑例如 typedef int (*foo)(void);
)。你的 View 1 和 View 2 示例不起作用:它们使 struct Cell
成为不完整类型,因此你实际上无法在代码中使用 child
。 - melpomenestruct node
{
int data;
struct node *next; // <-self reference
};
bool
,但绝对不会是蓝色的 ;) - avakar