MAKEINTRESOURCE() マクロ
MAKEINTRESOURCE() マクロは、リソース ID に関連づけられた LPTSTR へのポインタを返してくれるのだと思っていたのですが、どうやら違うようです。
こんな定義になってました。
#define IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0) #define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) #define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) #ifdef UNICODE #define MAKEINTRESOURCE MAKEINTRESOURCEW #else #define MAKEINTRESOURCE MAKEINTRESOURCEA #endif // !UNICODE
単に WORD 値を LPTSTR にキャストしているだけです。
なんで不正アクセスにならないんだろうと思ったんですが、どうやら Windows 上でのポインタは必ず 0x00010000 以上になるらしくて、関数内部では 0x0000xxxx だった場合に別の処理に分岐させて(IS_INTRESOURCE がリソース ID かどうかを判断するためのマクロ)、そこで頑張ってリソースの中から文字列を取り出しているようです。
なので当然、
// 文字列の先頭の文字を取得したい TCHAR h = MAKEINTRESOURCE(IDS_HOGE)[0]; // TCHAR h = _T("hoge")[0]; と等価……ではない。
こんなのを書いたら不正アクセスです。
ATL::CString の実装を見てみたんですが、ちゃんと内部で渡された値が 0x0000xxxx 以下(リソース ID)かどうかを判断して、リソース ID だった場合はその値を文字列に変換して代入してました。
リソース ID をポインタとして扱うことにものすごい違和感を感じる今日この頃。