BohYoh.comトップページへ
C & C++ FAQ
目次

C C++ 自己参照構造体へのtypedef名を与える宣言でエラーが出てしまいます。

C
 以下に示す線形リストのノードを表す構造体を例に考えましょう。

struct node { char name[20]; /* 名前 */ struct node *next; /* 後続ノードへのポインタ */ };

 構造体に与えられる名前nodeは、構造体タグと呼ばれます。この宣言によって作られるのは“node型”ではなく、“struct node型”であることに注意しまょう。すなわち、node単独では型名とはならないのです。
 一言で呼ぶことのできる手短な型名を与えるにはtypedef宣言によって、型に対する同義語を与える必要があります。
 ただし、宣言

typedef struct { char name[20]; /* 名前 */ Node *next; /* エラー */ } Node;

はエラーとなります。というのも、メンバnextの宣言時(3行目)においては、まだNode型の宣言が完了していないからです。  構造体の宣言をいったん完了した後にtypedef名を与えるとうまくいきます。すなわち、以下のように宣言しましょう。

struct node { char name[20]; /* 名前 */ struct node *next; /* 後続ノードへのポインタ */ }; typdef struct node Node; /* struct nodeの同義語Nodeを宣言 */

 なお、以下のように、typedef宣言を先に行うこともできます。

typdef struct node Node; /* struct nodeの同義語Nodeを宣言 */ struct node { char name[20]; /* 名前 */ Node *next; /* 後続ノードへのポインタ */ };

この場合、メンバnextは、Nodeへのポインとして宣言することができます。
 二つの宣言をまとめて、以下のように一度に宣言することもできます。

struct node { char name[20]; /* 名前 */ struct node *next; /* 後続ノードへのポインタ */ } Node;

メンバnextが、Nodeへのポインタではなく、struct nodeへのポインタであることに注意してください。

C++
 C++では、構造体、共用体、クラスの名前であるクラス名は、型名となります。したがって、

struct node { char name[20]; /* 名前 */ struct node *next; /* 後続ノードへのポインタ */ };

と宣言されていれば、node単独で型名となります。すなわち:

node a; // C++ではOK、Cではエラー struct node b; // C++、CともにOK

 C言語のようにtypedef名を導入する必要はなく、以下のようにさらに簡潔に宣言することができます。

struct node { char name[20]; // 名前 node *next; // 後続ノードへのポインタ };

メンバnextの宣言においてstructは不要となります。


■ 根拠 ■
標準C §6.5.2.3 Tags
標準C99 §6.7.2.3 The strcmp function
標準C++ §9.2 Class members

戻る

BohYoh.comロゴ