2015-09-08 20 views
14

次のコードは、gccの警告なしで正常にコンパイルされます。宣言されていない構造体によって警告が発生しない

構造体の前方宣言はありません。これは有効なCおよび/またはC++コードですか?

struct Foobar* f; 
struct Foobar* fun() { return 0; } 

int main() { f = 0; fun(); return 0; } 
+2

はい、有効です。 – erip

+7

構造体は宣言されていますが、定義されていません。これらの2つの用語は、しばしば互換的に使用されますが、異なることを意味します。 –

+3

これは、構造体がメンバー(リンクリストなど)として独自の型へのポインタを含むことを可能にするものです。型が有効であるために型を完全に宣言する必要はありません。 – DevSolar

答えて

26

これは不透明な構造と呼ばれ、エラーではありません。すべての構造体ポインタはCで同じ大きさなので、ポインタを操作するだけで構造体が持つフィールドを知る必要はありません。

変数Foobar(ポインタなし)を定義してみると、不完全な型エラーが発生します。

これにより、プライベートフィールドを持つタイプを持つことができます。 stdio.hのFILEタイプ

+4

必ずしもそうではありません。 * 'struct Foobar'型の変数を定義するとエラーになります。単に変数を宣言せずに宣言するだけでは( 'extern struct Foobar hello;')、エラーは発生しません。 – hvd

+1

@hvdそれは微妙な点ですが、大丈夫です、私の答えを修正しました。 – jforberg

11

C.

struct Foobar* f; 

で有効と同じである:Cで

struct Foobar; 
struct Foobar* f; 

不完全型struct Foobarを宣言し、それが不完全型へのポインタ・オブジェクトを宣言する。

タイプは別の翻訳単位で完了することができます。 (Cではオブジェクト、関数、不完全の3種類があります)。

あなたは不完全な型のオブジェクトを作成したり、型のサイズを取得することはできません。

struct Foobar x; // not valid 
sizeof (struct Foobar); // not valid 

をしかし、あなたは不完全型(struct Foobar* g;)またはtypedeftypedef struct Foobar Foobar;)へのポインタを作成することができます。

+0

「extern struct Foobar x;」を持ち、そのアドレスを取ることは合法でしょうか? – supercat

+0

@supercat:実際にどこかの周りに 'struct Foobar x'があるのでなければ、リンカエラーが発生するでしょう。 – Kevin

+0

@ケビン:当然、誰かが宣言をしなければならないだろうが、問題は、その構造体を使用する以外の目的で構造体を使用するコードの観点からは、「extern」が別の許容シナリオとしてリストされるべきかどうかである住所。 – supercat

関連する問題