C言語のユーザ定義型において、それが『どのタイプのユーザ定義型なのか』という情報はその型のオブジェクトを作る際に必要になる。
つまり、次のようなC/C++のコードがあったとして、
struct Hoge {
int foo;
int bar;
};
このHoge型のオブジェクトの作り方は少し違う、というオハナシ。
struct Hoge hoge; // C言語の場合; "struct"の部分が必須
Hoge hoge; // C++の場合; "struct"は無くてもいい
でもさ、C言語でオブジェクト宣言時にstructとかunionとかenumとワザワザ打ちたくない!!C++っぽく出来ないの!?
型定義時にtypedefする
typedefするその場合はこうする。
typedef struct {
int foo;
int bar;
} Hoge;
Hoge hoge; // C言語でも"struct"を打たなくてよくなる
とまぁ此処までは良くある話で、場合によっては入門書に書いてあったりもする。
タグ名を付ける
しかしこの場合、IDE上で開発していると、クラスの一覧表示において妙な名前で表示される場合がある。
例えばMicrosoft社のVC .NET 2003(ヴァージョン7.1)や2005(ヴァージョン8.0)の『クラスビュー』では__unnamed_0002_1のように表示され、Hogeは1個のtypedefとして別に名前だけ表示される。複数の同タイプのユーザ定義型が存在する場合、どの__unnamed_なんたら_かんたらがどのtypedef ~に対応するのかを判断する事は非常に困難となる。というかやりたくない。
それじゃ困るし、この方法ではリストを作る事が出来ない。という事でタグ名を付ける。
typedef struct tagHoge {
int foo;
int bar;
struct tagHoge *pointer; // 自分の型を指すポインタをメンバに出来る
} Hoge;
Hoge hoge;
これでIDE上にはそれぞれのタグ名で表示されるようになった。
これでも良いのだが……もう少し突っ込んでみる
さて、此処まででstruct等を付けずに済み、且つ自分の型を指すポインタを持つ事も出来るようになった。……が、イマイチ不満が残る。
typedef struct tagHoge {
int foo;
int bar;
struct tagHoge *pointer;
} Hoge;
Hoge hoge;
結局同じ型を指す名前が2つ存在する点、メンバとして宣言する場合には未だに定義型のタイプ指定が必要になる点だ。完全にタイプ指定の呪縛から開放されていないのである。
実はC言語ではユーザ定義型の名前と、typedefの名前の名前空間は異なる。structやunion、enumを付ける、付けないでどの名前か判断出来るからだろう。なので、タグ名とtypedef型名に同じ名前を付けてもエラーとはならない。C++でもこれは有効だ。
さらに、typedefはtypedefする元の型の定義がされる前でも機能する。つまり、typedef A B; struct A { ~ };という記述は合法なのである。
そこで、型の定義は次のように書ける事が分かる。
typedef struct Hoge Hoge;
struct Hoge {
int foo;
int bar;
Hoge *pointer;
};
Hoge hoge;
これで宣言時にstruct等を省略できる非常にC++風なユーザ定義型を作る事が出来る。
なお、3回も型名を書くのはイヤだ、タイプ量が増えるのが面倒だというのならば、少々見栄えが悪くなるが、#defineで最初の2行を関数マクロ化するといいのではなかろうか。
- こうする
- これって正式な名称って有るんだろうか?なんとなく『structハック』って呼んでるけど……
- 入門書に書いてあったりもする
- 定本 明解C言語 第1巻 入門編の278頁とか。この本、入門書としては薦められないけど。
- .NET 2003(ヴァージョン7.1)や2005(ヴァージョン8.0)
- 多分.NET(ヴァージョン7.0)も。使った事無いんで推測だけど。
因みに6.0ではこの場合きちんとtypedefした名前で表示されるし、タグ名をつけた場合はタグ名の方が表示されるようになっている(最も普通のtypedefは全く表示されないが)。これは改悪だと思うんだが、そこんとこどうよMicrosoft!! - タグ名と
typedef型名に同じ名前を付けてもエラーとはならない - 教えてくれた某専門学校のY先生に感謝。
- 合法
- イマイチ自信がなかったのでいろいろ調べてみたら、プログラミング作法の55頁にこのテクニックを使ったコードがあった。この本の作者の一人はC言語作成者でもあるBrian W.Kernighanなので大丈夫だろう。
