次のコードがあるとします。
typedef struct elementT {
int data;
struct elementT *next;
} element;
なぜそれを行う必要があり、構造体宣言自体の中でstruct elementT *next行うことができないのですか? element *nextまだ発表されてないからじゃない?
が定義されたtypedef後にのみ実行されます。struct次のコードを検討してください。構文は無効ですが、順序/優先順位が示されていることを期待しています。
typedef (struct {
int field1, field2;
}) item;
つまり、struct{...}はタイプを表す「式」です。はtypedef、名前を付けることでそのタイプを操作します。
対照的に、
struct foo {
foo *next;
};
Cの2つの特別なルールのために機能します:struct <name>タイプを定義するだけでstructなく、それにタグを与え、そのタグはstruct宣言の残りの部分の中にすぐに表示されます(明白な理由:リンクリスト、ツリーなどはこれらのルールなしで実装するのは非常に苦痛です)。
Cがそう言ったので:
(C99、6.2.1p7)「[...]他の識別子には、宣言子の完了直後に開始するスコープがあります。」
型nameelementTの一部である name はstruct elementT、コンパイラが 2 つの tokens を認識するとすぐに (不完全な型として) 見えるようになるstruct elementTため、構造体定義内で型名として使用できます。
typedef名elementである name は、識別子が表示されるまで表示されませんelement。これは、構造体定義の終了 (終了) の後です。}したがって、まだ存在しないという理由だけで、構造体定義内で使用することはできません。
私自身の個人的な好み (そして、多くの非常に賢い人々はこの点で私とは異なります) は、まったく使用typedefしないことです。型にはすでに完全に適切な名前がありstruct ElementTます。なぜ2番目のものを追加するのですか?私はちょうど書くだろう:
struct element {
int data;
struct element *next;
};
タイプを として参照しstruct elementます。
型に 1 単語の名前を付けることが十分に役立つと思われる場合は、もちろん、引き続き typedef を使用できます。typedef 名は、宣言が終了するまで表示されないことに注意してください。また、2 つの異なる識別子を使用する必要はありません。
typedef struct element {
int data;
struct element *next;
} element;
struct elementこれで、型を asまたは asとして参照できますelement。
struct(C++ には異なるルールがあることに注意してください。 (またはunion、、classまたはenum) 型の暗黙的な typedef を効果的に作成します。C++ では、typedefは不要ですが無害です。)
構造体宣言をその定義から分離すると、この動作を実現できます。
struct ElementT; // not strictly needed
typedef struct ElementT element; // this declares "struct ElementT" as well
struct ElementT
{
element * next;
};