私は長い間Cを書いていなかったので、この種の再帰的なことをどのように行うべきかわかりません...各セルに別のセルを含めたいのですが、エラーが発生します。 「フィールド'子'のタイプが不完全です」の行。どうしたの?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
明らかに、aは終わりのない再帰になるため、Cell
別のものを含めることはできません。Cell
ただし、Cell
CANには別のへのポインタが含まれています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;
}
おそらく標準ではこれよりもはるかに複雑ですが、コンパイラ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 を使用する必要があります。
この投稿が古いことは承知していますが、探している効果を得るには、次のことを試してください。
#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;
上記のコード フラグメントで説明した 2 つのケースのいずれでも、子の Cell 構造体をポインターとして宣言する必要があります。そうしないと、「フィールド 'child' has incomplete type」エラーが発生します。その理由は、「struct Cell」を定義して、コンパイラが使用時に割り当てるスペースを知る必要があるためです。
"struct Cell" の定義内で "struct Cell" を使用しようとすると、コンパイラは "struct Cell" が必要とする領域をまだ認識できません。ただし、コンパイラはポインターがどれだけのスペースを占めるかを既に認識しており、(前方宣言により) 「Cell」が「struct Cell」のタイプであることを認識しています (ただし、「struct Cell」の大きさはまだわかりません)。 )。したがって、コンパイラは、定義されている構造体内で「Cell *」を定義できます。
もう 1 つの便利な方法は、次のように構造タグを使用して構造を事前に型定義することです。
//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;
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 を優先します。
それ自体への参照を含む構造。リンクリストのノードを記述する構造でこれがよく発生します。各ノードには、チェーン内の次のノードへの参照が必要です。
struct node
{
int data;
struct node *next; // <-self reference
};
以前のすべての回答は素晴らしいです。構造体に独自の型のインスタンス (参照ではない) を含めることができない理由についての洞察を与えることを考えました。
構造体は「値」型であることに注意することが非常に重要です。つまり、実際の値が含まれているため、構造体を宣言すると、コンパイラーはそのインスタンスに割り当てるメモリの量を決定する必要があるため、すべてのメンバーを調べて追加します構造体のすべてのメモリを把握するためにメモリを増やしますが、コンパイラが内部に同じ構造体のインスタンスを見つけた場合、これはパラドックスです (つまり、構造体 A がどれだけのメモリを必要とするかを知るためには、メモリの量を決定する必要があります)構造体 A を取る !)。
ただし、参照型は異なります。構造体「A」に独自の型のインスタンスへの「参照」が含まれている場合、それに割り当てられているメモリの量はまだわかりませんが、メモリに割り当てられているメモリの量はわかっていますアドレス (つまり参照)。
HTH