質問の歴史:
C言語では、ある構造体が別の構造体を「知っている」必要がある場合がありますが、両方の構造体の定義が互いに依存している場合(相互入れ子)、片方の構造体を完全に定義することはできません。そこで、C言語では構造体の前方宣言(forward declaration)が用意されています。
問題:
前方宣言がなければ、コンパイラは構造体内で遭遇した型が何であるかを把握できず、未知の型のエラーを出します。別の構造体を値としてではなくポインタとして含む構造体を作成しようとした場合や、構文が誤っている場合にエラーが発生することがよくあります。
解決策:
前方宣言は、構造体の完全な定義を開示せずにその構造体のポインタを作成する必要がある場合に使用されます。構文は struct A; です。完全な定義(struct A { ... };)は後で行うことができます。
コードの例:
struct B; // 前方宣言 struct A { int val; struct B *link; }; struct B { int id; struct A *parent; };
主な特徴:
前方宣言を通じて「他の構造体の値型」のフィールドを作成できますか?
いいえ、前方宣言は型をポインタとしてのみ使用することを許可します。さもなければエラーになります:型のサイズが不明です。
struct B; // ok struct A { struct B b; // エラー:Bのサイズは不明 };
異なるファイルで作業する際に前方宣言をどこに配置するのが正しいですか?
前方宣言は、構造体がポインタとしてのみ使用される場合にヘッダーに配置します。完全な定義は別のヘッダーに置くか、実装ファイルに置きます。
前方宣言は構造体のサイズや適切なメモリ割り当てに影響を与えますか?
いいえ、Cは「未定義」の構造体のサイズを知らないため、ポインタは常に同じサイズを持ち、宣言された型に関係なく、使用するコンパイラによって同じサイズを持ちます。
ヘッダーファイル内の両モジュールが相互に値としてフィールドを持つ構造体を含んでいました。ビルドは未定義の型のエラーで失敗しました。
利点:
欠点:
あるプログラマーが前方宣言とポインタを使用し、ヘッダー内の冗長な依存関係を最小限に抑えました。コードのコンパイルと保守が容易になりました。
利点:
欠点: