次のコードがあるとします。
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;
};