Version 6.03
別名に注意!
『この前はクラスのメンバ変数の話をしたんだよね』
「 . や -> でメンバ変数にアクセスしたら、その変数だけに注目すればい
い、ってことでした。今回は、型関係のエラーの続き」
『そうそう、関数の引数に渡すときとかよくあるんだけど』
「特に API はそうでしょ。意味不明な型が結構あるからね。たとえば
WPARAM や LPARAM 」
『メッセージの時に出てきたのだね』
「 WPARAM は unsigned int で LPARAM は long 。これが実際にそうなって
るのは Windef.h ってファイル」
typedef UINT WPARAM;
typedef LONG LPARAM;
『 typedef って……あ、 Ver 5.08 ( No.073 ) でやったね。型に違う名前
付けるのだ』
「そう。ここでは UINT の新しい名前に WPARAM を、 LONG の新しい名前に
LPARAM を加えてます」
『……で、 UINT は? LONG って?』
「それも同じファイルの上の方で typedef されてるから」
typedef unsigned int UINT;
「あ、 LONG は別だね。 Wtypes.h だ」
typedef long LONG;
『結局 unsigned int と long だったってわけね』
「これをどう調べるかって言うのは」
『ファイルから検索、でしょ』
「そう。【編集】−【ファイルから検索】で検索。検索場所は、 API 関連
のファイルが置いてある MICROSOFT VISUAL STUDIO\VC98\Include で」
『そこには API のファイルしかないの?』
「 API と、ランタイムのヘッダーファイル。だから一緒にランタイムも調
べることになるかな」
『質問! 実際に調べると、 WPARAM とかで調べると一杯出てきちゃうんだ
けど』
「検索一覧をクリックしてから Ctrl + F で」
『あ、検索ダイアログが!』
「それで typedef を検索、とか」
『なるほど。もひとつ質問! LONG で検索したら Wtypes.h だけじゃなく
て Winnt.h でも見つかったんだけど、どっち?』
「場合によって」
『ばあいによってぇ!?』
「そうなんだって、ホントに。この例はどっちも同じ long だからいいけ
ど、ものによってはファイルによって何の型か違うことがあるし」
『……それってつまり、 typedef char LONG ってことがあるかもしんない
ってこと? なにそれわけ分かんない!』
「まーまー。手っ取り早く、ホントは何の型か調べるときにはこういうふう
にしましょう」
WPARAM wParam;
int *pi = wParam;
『?』
「こうするとこういうコンパイルエラーが出ます」
error C2440: 'initializing' :
'unsigned int' から 'int *' に変換することはできません。
「これで wParam の型が unsigned int だって分かるわけ」
『うわ、コンパイルエラーで型調べるの!? そーゆーのっていいの?』
「もちろん。ちなみに int * は何でもいいんだけど、このエラーは〈 = で
右から左に代入できないとき〉に出るから」
『代入できない型にするんだ。ってことは調べたい型が int * っぽかったら
他のにした方がいいのね』
「ポインタ以外はポインタに、ポインタはポインタ以外に、ってとこかな」
『最後の質問!! なんでわざわざこーゆーしちめんどくさいことしてる
の? WPARAM なんて書かずに直接 unsigned int って書けばいいじゃん』
「建前上は、あとで型を変えることができる、っていう理由から」
『建前上はぁ?』
「たとえば、 C++ 言語の規則が変わって〈 int がなくなった!〉って場合
に」
『そんなことになったら int で書いてる部分全部直さないと』
「でも UINT を使ってたら、 typedef unsigned int UINT を書き換えるだ
けで」
『全部いっぺんに変えられる!』
「そういう利点があるから。ただその分、必要ない部分を変えちゃったら」
『いっぱい問題が出てくるね……』
「それに、他の OS では使えないし」
『どゆこと?』
「 UINT なんかの型は Windows API だけのものだから。他の OS でプログ
ラム組むときには使えないから」
『ってことは、各 OS ごとにそーゆー API があるの?』
「そういうこと。ウィンドウズに絞ってある程度やっておけば、他のでもあ
る程度通用すると思うから安心して」
『はーい』
「それにも関連してるんだけど、 API は実はこの typedef の嵐だったりし
ます。たとえば」
typedef int INT;
「が Windef.h にあります」
『うわ、 int にも!』
「他によく出てくるのが DWORD とか WORD とか BYTE とか。こういうのは
Wtypes.h にあるね」
『こーゆーのの型も調べなきゃいけないんだ』
「一度は直に見た方がいいよ。ま、簡単に言えば BYTE が unsigned char
で WORD が unsigned short 。 DWORD は double WORD の略だから」
『 double 、倍…… short の倍は4バイトだから、 unsigned long なんだ
ね、 DWORD は』
「そういうこと。で、まとめると、こういうふうに型に違う名前を付けるの
が API のポリシーってこと」
『趣味悪そう……』
「同じようなので、ポインタでこういう typedef してるのもあります」
『知ってる! LPCTSTR とかだよね』
「それだけじゃないよ。さっき言った DWORD のポインタ版 LPDWORD とか」
『……もしかして LPINT も?』
「あります。 Windef.h にね」
typedef int near *PINT;
typedef int far *LPINT;
『??? なんか謎。 near とか far とかって?』
「これはね、 Windows 3.1 って知ってる?」
『大昔のウィンドウズだよね』
「大昔……まーそういうことで。今はポインタのサイズは?」
『32ビット』
「だけど、大昔はそんなにコンピューターに余裕なかったから、小さいポイ
ンタと大きいポインタのふたつを用意してたんです」
『それが near と far なんだ。近くと遠く?』
「アドレスで考えるとそういうこと、ってことなんだろうね。で、 near は
小さいから普通に P 、 far は long サイズのポインタだから LP を付ける
わけ」
『そっか、今は全部大きいポインタだからどれも LP の付いてる方使ってる
んだ!』
「一応ね」
『一応?』
「上の方でこういうのあるでしょ」
#define far
#define near
「 #define って憶えてる?」
『 Ver 4.09 ( No.059 ) でやったね。あれ、でもあれは……』
「そう。たとえば」
#define DEF_FLAG_OK 1 // 定数。
『これだったら、 DEF_FLAG_OK を 1 に置き換える……って、そういえばこ
れって typedef みたいだね』
「そだね、 typedef は #define の機能を〈型の名前〉だけに機能するよう
にしたものって言えるかも」
『ほほう』
「で、 #define far は、 1 にあたる部分が何もない、つまり〈空白〉に
なってるわけだから」
『ってことは far や near は空白に置き換えられる?』
「そういうこと! つまり、これらの単語が出てきたら消されちゃうってこ
と」
『あ! だから PINT も LPINT も同じなんだ』
「だからどっちを使ってもいいんだけど、基本的には LP 付いてる方。もー
しかしたら、 Windows 3.1 に移植することがあって、そのときその方が楽
だから」
『絶対ないような気がするんだけど』
「それがある業界なんだよね……あ、あと最後に const について」
『引数に使う const って前にかなりしっかりやったよね』
「 Ver 4.12 ( No.062 ) だね。そこでもやったけど」
int のアドレスを int * へ
int のアドレスを const int * へ
const int のアドレスを const int * へ
「はコンパイルエラーにならないけど」
const int のアドレスを int * へ
「はコンパイルエラーになります」
『ようするに、書き換えちゃいけないのを書き換えるようにしちゃいけな
いってことだよね』
「そういうこと。これはさっき言った typedef のにも当てはまるからね」
『あ、そっか、 LPCTSTR と LPTSTR もこれなんだもんね』
「さて、型関係のエラーはこの辺……ってことにしといて」
『ぶーぶー、もっといっぱいあるよ確かー』
「〈コンパイルエラーは論外〉って言った手前なんだけど、コンパイルエ
ラーが起きるからには理由があるわけで、その理由を知らないと」
『教えてもらっても理解できない、ってことねー』
「そゆこと。その辺はこれから少しずつ教えてくから」
/*
Preview Next Story!
*/
『教えてもらうまでは大変ね……』
「僕も昔はホント、色々失敗したけどね」
『そういうもん?』
「うまくいったけど理解できてないコードを ML に載せたり……」
『ありゃりゃ……』
「というわけで次回」
< Version 6.04 あるのにない!! >
『ねぇ、今教えてくれてるのにはそういうことないのぉ?』
「……ギクっ……」
『ツッコむとこでしょそこは……』