我已经很长时间没有写C了,所以我不确定应该如何去做这些递归的事情……我希望每个单元格都包含另一个单元格,但是随着“字段'child'的行类型不完整”。这是怎么回事?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
我已经很长时间没有写C了,所以我不确定应该如何去做这些递归的事情……我希望每个单元格都包含另一个单元格,但是随着“字段'child'的行类型不完整”。这是怎么回事?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
Answers:
显然,一个单元不能包含另一个单元,因为它变成了永无止境的递归。
但是,一个单元格可以包含指向另一个单元格的指针。
typedef struct Cell {
bool isParent;
struct Cell* child;
} Cell;
Cell
不在范围内。
Cell*
给时,我会收到警告cell->child
。
struct
C中的s基本上只是将它们的所有值彼此相邻地存储,因此实际上不可能在自身中存储一个结构(因为该结构将必须包含另一个结构,依此类推,从而导致无限大的内存结构) 。
在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
直到最后一行才知道:-)这就是我记住该规则的方式。
从理论上讲,语言只能支持自我指称结构,而不能支持自我包含结构。
有一种解决方法:
struct Cell {
bool isParent;
struct Cell* child;
};
struct Cell;
typedef struct Cell Cell;
如果这样声明,它将正确地告诉编译器struct Cell和plain-ol'-cell是相同的。因此,您可以像平常一样使用Cell。虽然还必须在初始声明本身内部使用struct Cell。
struct Cell;
?
struct Cell
。
struct Cell;
冗余。但是,如果由于某种原因在将前两行定义结构之前,将后两行放入要包含的头文件中Cell
,则多余的部分struct Cell;
是必要的。
typedef struct Cell Cell;
它,它将成为Cell
的别名struct Cell
。编译器是否曾经见过都没关系struct Cell { .... }
。
我知道这篇文章很旧,但是,要获得想要的效果,您可能需要尝试以下方法:
#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'has notcomplete type”错误。原因是必须定义“结构单元”,以便编译器知道使用时分配多少空间。
如果尝试在“ 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;
但是最后一个选择通常会增加一些多余的行和单词的数量(我们很懒惰,您知道;))。因此,最好使用View 2。
typedef
语法的解释不正确(请考虑例如typedef int (*foo)(void);
)。您的View 1和View 2示例不起作用:它们struct Cell
的类型不完整,因此您实际上不能child
在代码中使用。
另一种方便的方法是使用带有结构标签的结构预先定义类型:
//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;