2012-11-09 15 views
6

私は 'The C Programming Language'を読んでおり、のtypedefに関する問題を抱えていました。です。我々はTNODEはまだ、まだ宣言されていませんが、我々はすべてのコンパイルエラーを取得しない、 私たちは、上記のステートメントを変更したときにstruct typedef内の宣言ルール

typedef struct tnode *Treeptr; 

を書く時までに

typedef struct tnode *Treeptr; 
typedef struct tnode { /* the tree node: */ 
    char *word; /* points to the text */ 
    int count; /* number of occurrences */ 
    struct tnode *left; /* left child */ 
    struct tnode *right; /* right child */ 
} Treenode; 

:コードは次のようです:

error: parse error before '*' token 
warning: data definition has no type or storage class 

typedef Treenode *Treeptr; 

私たちは、コンパイル・エラーが発生します

違いは何ですか? "struct tnode"は "Treenode"と同じではありませんか?

+0

[このコードをコンパイルできるのは、C標準のどの部分ですか?](http://stackoverflow.com/questions/12200096/which-part-of-the-c-standard-allows-this-code -to-compile)と[C標準では、このヘッダに1つまたは2つの 'struct uperms_entry'タイプがあると考えますか?](http://stackoverflow.com/questions/11697705/does-the-c-standard-considerそれは関連するものとして、あなたがどこにいるかを超えたレベルで投げられるかもしれません。 –

答えて

6

タイプが定義される前に使用することはできません。

typedef struct tnode { ... } Treenode;宣言では、タイプTreenodeはセミコロンに達するまで定義されません。

typedef struct tnode *Treeptr;の状況が異なります。これはコンパイラに 'struct tnodeという構造体型があり、Treeptr型がstruct tnode'へのポインタのエイリアスであることを伝えます。その宣言の最後に、struct tnodeは不完全な型です。不完全な型へのポインタを作成することはできますが、不完全な型の変数を作成することはできません(したがって、Treeptr ptr1;またはstruct tnode *ptr2;を定義でき、それらは同じ型ですが、struct tnode node;を定義することはできません)。

struct tnodeの本体は、のように書くことができる:構造が定義される前Treeptrタイプstruct tnode *ための既知のエイリアスであるため

typedef struct tnode 
{ 
    char *word; 
    int  count; 
    Treeptr left; 
    Treeptr right; 
} Treenode; 

Treenodeは、最後のセミコロンに達するまで(大体言えば)既知のエイリアスではないため、Treenode *left;を使用することはできません。

0

typedef struct tnode *Treeptr;には、 "tnode"構造体の暗黙的な前方宣言があります。あなたがTreePtrを宣言するとき、あなたは構造体を実装していない

typedef struct tnode Treenode; 
typedef Treenode *Treeptr; 

struct tnode { /* the tree node: */ 
    char *word; /* points to the text */ 
    int count; /* number of occurrences */ 
    struct tnode *left; /* left child */ 
    struct tnode *right; /* right child */ 
}; 
1

:それはに似ています。これは、 "前方宣言"として知られています。次のようなものがあります:「ここではこれを使用しますが、後でそれをよりよく説明します」。実装は、後で、一度だけ現れなければならず、それは2番目のtypedefで見つかるものです。

TreePtrは実際にはポインタをbeeingするという新しいタイプになるため、structと同じではありません。

+0

ありがとう、フェリックス、素敵な説明。したがって、 'struct undefined_struct * a;'は許されますが、 'struct undefined_struct b 'と言う前に' undefined_struct'を実装する必要があります、それは正しいのですか?しかし、この "_foward declaration_"の意図は何ですか? – Rain

+1

先行宣言、 'struct a'は' struct b'へのポインタを含み、 'struct b'は' struct a'へのポインタを含むように、相互に再帰的な構造を作ることができます。不完全な型のより緊密な理由は、不完全な型へのポインタの観点から関数のセットに対するインタフェースを定義することができ、パブリック・ヘッダーは決して必要ではありません(つまり、前の宣言が不可能な場合は本当の問題です)。 –

+0

'struct undef a;'、 'struct undef * b;'などのようなものを任意の組み合わせで行うことができます。あなたが必要とするほど多くのことができます。それらを別の構造体の中に入れます。しかし、構造体の実装を一度、どこでいつでも好きなときに宣言する必要があります。 –

関連する問題