VCでSetWindowLongPtrを使用したときの警告の対処法

32ビット環境ではSetWindowLongPtrはSetWindowLongのエイリアスになります。それとは別に、VCのデフォルトでは /Wp64 オプションが有効になっています。これは64ビットOSへの移植性が損なわれる場合に警告を出すと言うもので、

void* p = &p;
unsigned long i = (unsigned long)p; // C4311

上記のようなキャストをする際に警告(C4311)を出してくれるというもの。64ビット環境ではポインタは64ビットになるので、32ビットのlong型にキャストするのはまずいよ、と言ってくれます。

どちらもそれだけで見ればどうということないものなのですが(むしろ警告は便利)、SetWindowLongの第三引数はlong型なので、こいつにポインタを渡す場合longにキャストする必要があり、そこで警告が出てしまいます。SetWindowLongPtrであれば問題ないのですが、前述の通り32ビット環境ではSetWindowLongPtr==SetWindowLongなので、どちらを使っても警告が出てしまいます。

/Wp64を無効にするのは簡単だけれども、それはなんだか負けた気がするので、少し調べてみました。

Bugslayerにはpragmaで警告を無効にするよう書いてあるけれど、下のブログのコメントにもっとよさげなコードが。

# re: SetWindowLongPtr and /Wp64
Billy
Posted @ 3/12/2007 11:03 AM
SetWindowLongPtr(0, 0, (__int3264)(LONG_PTR)x);

It took me forever to figure that out...

__int3264とはビルド環境によって、int32もしくはint64になるものらしい。これを利用することで、どちらの環境でも警告を出すことなくビルドできるそうな。素晴らしい! ということでこれを利用することにしました。それにしても__int3264なんてあやしげな(ソース見れば一目瞭然ですけれど)マクロもあるんですね。奥が深いというかなんというか。