HANDLE
読み:ハンドル
外語:HANDLE

 Microsoft WindowsAPIなどに使われている、Windows用C言語の変数型の一つで、ハンドルを表わす。
目次

特徴
 HANDLE型は、Microsoft Visual C++ 2003ではwindef.hで、Microsoft Visual C++ 2008ではWinNT.hで、次のように定義される。
 typedef void *HANDLE;
 つまり、HANDLE型はvoid *型である。

定義

序論
 Windowsにおいては、ハンドルはポインターとして扱われ、それの変数型がHANDLE型などである。そして、その実態はvoid *である。
 つまり、ポインターであること自体に意味があるのであって、そのポインターが指し示す内容については一切の考慮がない。OS側からも情報を提供しなければ、プログラマーもその先の情報には一切手を触れない。
 ではなぜポインターなのかというと、実際にはWindowsが内部で利用する構造体に対するポインターであるからで、これを各オブジェクトの識別に利用するのである。
 ポインターが識別に利用できるのは、次のような条件が整っているからである。

問題
 旧来は全てのハンドルはHANDLE型であったが、現在はやや異なっている。
 なぜなら、ハンドルとはいっても異なるオブジェクトのハンドル同士は全く互換性がないからで、例えばウィンドウハンドル(HWND)とインスタンスハンドル(HINSTANCE)は共にハンドルであってもその構造や用途は全く違う。従って、HWND型の変数にHINSTANCE型変数を代入するなどということは、絶対にあり得ないわけである。
 しかし、あり得ない代入であっても共にHANDLE型つまりvoid *であれば、コンパイラーはその違いを認識できない。これが発見困難な、致命的なバグにも繋がりかねない。そこで技巧を凝らし、MicrosoftはDECLARE_HANDLEマクロという結論に至った。

DECLARE_HANDLE
 Microsoft Visual C++ 2003環境などでは、例えば、次のように利用されている。
 DECLARE_HANDLE (HWND)
 DECLARE_HANDLEは、winnt.hで、次のように定義されている。
 #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
 nameにHWNDを代入し、このマクロを展開すると、次のようになる。
 #define struct HWND__ { int unused; }; typedef struct HWND__ *HWND
 つまり、int型の変数unused(未使用の意)を持った構造体HWND__へのポインター変数*HWNDを定義する構造となる。
 構造体であれば、その違いをコンパイラーは認識できるので、不正な代入があればエラーとして弾くことができる。但しその中身については操作・参照するものでないので、適当にint型で、かつ名前がunusedとなっているわけである。実際にunused変数を操作した場合の動作については保証されない(恐らく、アクセス違反となるだろう)。

再検索