145

私は長い間Cを書いていなかったので、この種の再帰的なことをどのように行うべきかわかりません...各セルに別のセルを含めたいのですが、エラーが発生します。 「フィールド'子'のタイプが不完全です」の行。どうしたの?

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

9 に答える 9

202

明らかに、aは終わりのない再帰になるため、Cell別のものを含めることはできません。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;

上記のコード フラグメントで説明した 2 つのケースのいずれでも、子の Cell 構造体をポインターとして宣言する必要があります。そうしないと、「フィールド 'child' has incomplete type」エラーが発生します。その理由は、「struct Cell」を定義して、コンパイラが使用時に割り当てるスペースを知る必要があるためです。

"struct Cell" の定義内で "struct Cell" を使用しようとすると、コンパイラは "struct Cell" が必要とする領域をまだ認識できません。ただし、コンパイラはポインターがどれだけのスペースを占めるかを既に認識しており、(前方宣言により) 「Cell」が「struct Cell」のタイプであることを認識しています (ただし、「struct Cell」の大きさはまだわかりません)。 )。したがって、コンパイラは、定義されている構造体内で「Cell *」を定義できます。

于 2012-03-24T01:47:42.617 に答える
5

もう 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;
于 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」に独自の型のインスタンスへの「参照」が含まれている場合、それに割り当てられているメモリの量はまだわかりませんが、メモリに割り当てられているメモリの量はわかっていますアドレス (つまり参照)。

HTH

于 2016-12-11T17:28:27.770 に答える