我没有写C很长时间,所以我不确定我应该怎么做这些递归的东西...我希望每个单元格包含另一个单元格,但我得到一个“field'child''的错误是”类型不完整“。怎么了?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
答案 0 :(得分:163)
显然,Cell不能包含另一个单元格,因为它变成永无止境的递归。
但是,Cell CAN包含指向另一个单元格的指针。
typedef struct Cell {
bool isParent;
struct Cell* child;
} Cell;
答案 1 :(得分:22)
在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
的情况。直到最后一行:-)这就是我记得那条规则的方式。
答案 2 :(得分:15)
从理论的角度来看,语言只能支持自我指涉的结构而不是自我包容的结构。
答案 3 :(得分:12)
有一种解决方法:
struct Cell {
bool isParent;
struct Cell* child;
};
struct Cell;
typedef struct Cell Cell;
如果你这样声明,它会正确告诉编译器struct cell和plain-ol'-cell是相同的。所以你可以像平常一样使用Cell。尽管如此,仍然必须在初始声明中使用struct Cell。
答案 4 :(得分:8)
我知道这篇文章已经过时了,为了获得您想要的效果,您可能需要尝试以下方法:
#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结构声明为指针。如果你不这样做,那么你将得到“字段'子'具有不完整类型”错误。原因是必须定义“struct Cell”,以便编译器知道在使用它时要分配多少空间。
如果您尝试在“struct Cell”的定义中使用“struct Cell”,那么编译器还不能知道“struct Cell”应该占用多少空间。但是,编译器已经知道指针占用了多少空间,并且(使用前向声明)它知道“Cell”是一种“struct Cell”(尽管它还不知道“struct Cell”有多大) )。因此,编译器可以在正在定义的结构中定义“Cell *”。
答案 5 :(得分: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;
但是最后一个选项增加了一些额外的行和单词通常我们不想做(我们很懒,你知道;))。所以更喜欢View 2。
答案 6 :(得分: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;
答案 7 :(得分:1)
包含对自身的引用的结构。在描述链接列表的节点的结构中常见的情况。每个节点都需要引用链中的下一个节点。
struct node
{
int data;
struct node *next; // <-self reference
};
答案 8 :(得分:1)
以前的所有答案都很棒,我只想深入了解一个结构为什么不能包含自己类型的实例(不是参考)。
非常重要的是要注意结构的价值和价值。类型,即它们包含实际值,所以当你声明一个结构时,编译器必须决定分配给它的一个实例多少内存,所以它通过它的所有成员并加上它们的内存来计算出所有的内存。结构,但如果编译器发现内部相同结构的实例,则这是一个悖论(即,为了知道结构A需要多少内存,你必须决定结构A需要多少内存!)。
但是参考类型是不同的,如果结构&#39; A&#39;包含&#39;参考&#39;虽然我们还不知道分配了多少内存,但我们知道有多少内存被分配给内存地址(即引用)。
HTH