Microsoft WindowsのAPIなどに使われている、Windows用C言語の変数型の一つで、ハンドルを表わす。
Microsoft Visual C++ 2003環境では、HANDLE型として、windef.hで次のように定義される。
typedef void *HANDLE;
つまり、HANDLE型はvoid *型である。
Windowsにおいては、ハンドルはポインタとして扱われ、それの変数型がHANDLE型などである。そして、その実態はvoid *である。
つまり、ポインタであること自体に意味があるのであって、そのポインタが指し示す内容については一切の考慮がない。OS側からも情報を提供しなければ、プログラマもその先の情報には一切手を触れない。
ではなぜポインタなのかというと、実際にはWindowsが内部で利用する構造体に対するポインタであるからで、これを各オブジェクトの識別に利用するのである。
ポインタが識別に利用できるのは、次のような条件が整っているからである。
旧来は全てのハンドルはHANDLE型であったが、現在はやや異なっている。
なぜなら、ハンドルとはいっても異なるオブジェクトのハンドル同士は全く互換性がないからで、例えばウィンドウハンドル(HWND)とインスタンスハンドル(HINSTANCE)は共にハンドルであってもその構造や用途は全く違う。従って、HWND型の変数にHINSTANCE型変数を代入するなどということは、絶対にあり得ないわけである。
しかし、あり得ない代入であっても共にHANDLE型つまりvoid *であれば、コンパイラはその違いを認識できない。これが発見困難な、致命的なバグにも繋がりかねない。そこで技巧を凝らし、Microsoftは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変数を操作した場合の動作については保証されない(恐らく、アクセス違反となるだろう)。