別の質問への回答の一環として、このようなコードに出くわしました。これは、gcc が問題なくコンパイルします。
typedef struct {
struct xyz *z;
} xyz;
int main (void) {
return 0;
}
これは、自分自身を指す型 (リンクされたリストなど) を構築するために常に使用してきた手段ですが、自己参照を使用できるように構造体に名前を付ける必要があると常に考えていました。xyz *z
つまり、その時点では typedef がまだ完成していないため、構造内で使用できませんでした。
ただし、この特定のサンプルでは構造体に名前が付けられておらず、それでもコンパイルされます。構造体と typedef の名前が同じだったため、上記のコードを自動的に変換するコンパイラで黒魔術が行われていると最初は思っていました。
しかし、この小さな美しさも同様に機能します。
typedef struct {
struct NOTHING_LIKE_xyz *z;
} xyz;
ここで何が欠けていますか?struct NOTHING_LIKE_xyz
どこにもタイプが定義されていないため、これは明らかな違反のようです。
ポインターから実際の型に変更すると、予想されるエラーが発生します。
typedef struct {
struct NOTHING_LIKE_xyz z;
} xyz;
qqq.c:2: error: field `z' has incomplete type
また、 を削除するとstruct
、エラー ( parse error before "NOTHING ...
) が表示されます。
これはISO Cで許可されていますか?
更新: Astruct NOSUCHTYPE *variable;
もコンパイルされるため、有効と思われる構造内だけではありません。c99 標準には、構造体ポインターに対してこの寛大さを許すものは何も見つかりません。