Version 8.14
構造体を読み解く
「さて、今回は前回使った」
typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
#if (_WIN32_IE >= 0x0400)
union
{
TVITEMEX itemex;
TVITEM item;
} DUMMYUNIONNAME;
#else
TVITEM item;
#endif
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
「を読み解きます」
『かなり複雑……』
「それは、いろんなものが複雑に絡み合ってるから。しかも、それぞれが独
立してるものだから」
『順に憶えていけば大丈夫?』
「大丈夫。じゃ、まずは外側、構造体全体の話から」
typedef struct tagTVINSERTSTRUCT {
// 略
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
『これでくくってあるってことは、この頭のと最後のとが関係してるってこ
と?』
「そういうこと。えっと、 typedef は教えたよね」
『 Version 5.08 ( No.073 ) でね』
「ここでは」
typedef struct tagTVINSERTSTRUCT {
// 略
} TVINSERTSTRUCT;
「と」
typedef struct tagTVINSERTSTRUCT {
// 略
} FAR *LPTVINSERTSTRUCT;
「が組み合わさってるって考えて」
『 , でふたつ一緒に型を作れるのね』
「で、まずは上の」
typedef struct tagTVINSERTSTRUCT {
// 略
} TVINSERTSTRUCT;
「から。これは」
struct tagTVINSERTSTRUCT {
// 略
};
「って構造体の別名として TVINSERTSTRUCT の付けてる……」
『付けてる?』
「みたいな感じ」
『何それ』
「前回の CTreeCtrl::InsertItem() で試してみると分かるけど、
tagTVINSERTSTRUCT そのものは型になってません」
『へ? 型として使えないの?』
「そう、だからただの名前、何にも使えない名前」
『いみなー』
「だから実際には」
typedef struct tagTVINSERTSTRUCT {
// 略
} TVINSERTSTRUCT;
「は、この構造体を TVINSERTSTRUCT って名前で使う、って意味だと考えて
ください」
『……質問!』
「はい火美ちゃん」
『前に、構造体はクラスと同じだって教えてもらったよね』
「 Version 7.07 ( No.127 ) でね」
『ってことは』
struct TVINSERTSTRUCT {
// 略
};
『でいいんじゃないの?』
「今はね」
『あ、昔は違ったって話?』
「そゆこと。クラスがない、 C 言語の時代にはこの書き方では構造体は作
れなかったんです」
『だから typedef 使ってた?』
「そゆこと。そういう書き方しか前はできなくて、それが今も API には
残ってるってこと」
『じゃあ、昔の typedef 使ったのは今の書き方に読み替えちゃっていい
の?』
「うん、それで大丈夫だと思うよ。じゃ、その次の」
typedef struct tagTVINSERTSTRUCT {
// 略
} FAR *LPTVINSERTSTRUCT;
『んーと、 FAR * ってのが増えたんだね』
「 FAR は Version 6.03 ( No.103 ) の far が #define されたもので、こ
こで書いてあるとおり空白になります」
『ってことは * だけ、ってことはポインタ?』
「そう。 typedef は最後の単語だけが新しい型の名前って指定されるか
ら、ここでは〈構造体のポインタ〉として LPTVINSERTSTRUCT って型が作ら
れてることになります」
『これって』
typedef TVINSERTSTRUCT *LPTVINSERTSTRUCT;
『でもいいんだよね』
「もちろん。一緒に型を定義するのは昔の C 流ってとこかな。逆に言え
ば、ここでも」
『さっきみたいにこう読み替えちゃえばいいのね』
「そゆこと。さて、次に構造体の中身」
HTREEITEM hParent;
HTREEITEM hInsertAfter;
『はただのメンバ変数だよね。次の』
#if (_WIN32_IE >= 0x0400)
『はプリプロセッサだね #if は Version 6.06 ( No.106 ) でやったけど、
_WIN32_IE はなに?』
「これは組み込みマクロのひとつ」
『 Version 6.07 ( No.107 ) でやったね。 WIN32 ってどういう意味?』
「 WIN32 は32ビットウィンドウズっ意味だけど、まぁ〈最近のウィンド
ウズ〉って読み替えていいかな。 Version 2.14 ( No.025 ) 参照」
『今日は参照多いね…… IE って、インターネットエクスプローラー?』
「そう。つまりこの組み込みマクロは、 IE のバージョンを示してるんで
す」
『 IE のバージョンなんて関係あるの?』
「あるんです。実はツリービューコントロールってウィンドウズ95が出た
頃よりもバージョンアップしてて、そのバージョンアップって IE と一緒に
されてるから」
『ってことは IE4 が入ってるか入ってないかでツリービューコントロール
のできることが違う?』
「そう、だからバージョンを調べて構造体の中身を変えてるんです」
『これだと、 IE のバージョンが低いと』
typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
TVITEM item;
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
『で、高いと』
typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
union
{
TVITEMEX itemex;
TVITEM item;
} DUMMYUNIONNAME;
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
『なわけね』
「そゆこと。ここまで分かれば、あとは」
『 union だけ! これは初めて見るのだね』
「そうだね。これって C 言語の時代からあるんだけど、分かりにくいのと
ちょっと危険なのだからあまり使われてないかな」
『憶えても使わない方がいい?』
「だね。でも使い方だけは教えておくから。まず」
union
{
TVITEMEX itemex;
TVITEM item;
} DUMMYUNIONNAME;
「の DUMMYUNIONNAME は無視して」
『ダミーって付いてるものね。さっきの typedef struct
tagTVINSERTSTRUCT の名前だけってのと同じ?』
「そんなとこ。で、 union の中身について。 union は〈あるメモリ領域を
いろんな変数に見せかける〉ことができます」
『???』
「つまり」
typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
TVITEM item;
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
「でもあるし」
typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
TVITEMEX itemex;
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
「でもあるってこと」
『どっちの変数にもなる?』
「そう。次の例が一番分かりやすいかな」
TVINSERTSTRUCT stInsertItem;
TRACE( "%X\n", &( stInsertItem.item ) );
TRACE( "%X\n", &( stInsertItem.itemex ) );
// 64F4B8
// 64F4B8
『お、普通に item と itemex と両方使ってて……アドレスが同じ!』
「そう、ふたつメンバ変数があるように見えるけど、実際には同じメモリ上
に置かれてて、〈どういう型として扱うか〉だけが異なるってこと」
『……それってまずくない? たとえば、ここで TVITEM item の代わりに
int i とかやっても』
「できちゃいます」
『……それってヤバくない?』
「やばいよ。だからあまり使われてないし、こういう使い方も勧めないか
ら」
『まさに教わるだけってことね』
/*
Preview Next Story!
*/
『教わるだけのって……やっぱいつか使いたくなるかな』
「絶対なるよ」
『お、経験者は語る?』
「 C++ って、型がコンパイル時にチェックされるでしょ」
『 HWND に int 入れられないものね』
「そのあたりの柔軟性が欲しい時に……」
『 union に手を出しちゃうわけね』
「というわけで次回」
< Version 8.15 通知メッセージの受け方 >
『につづく!』
「 union は MFC もメッセージ処理に使ってたりするし」
『なら大丈夫なんじゃない?』
「どうかなぁ……」