32回以上左シフトするには、左辺を64bit整数型にする。
int _tmain(int argc, _TCHAR* argv[]) { int rhs32 = 63; __int64 rhs64 = 63; // NG { __int64 flags = 1 << rhs32; printf("%llx\n", flags); } // OK { __int64 flags = static_cast<__int64>(1) << rhs32; printf("%llx\n", flags); } // NG { __int64 flags = 1 << rhs64; printf("%llx\n", flags); } // OK { __int64 flags = static_cast<__int64>(1) << rhs64; printf("%llx\n", flags); } return 0; }
右辺のサイズは関係なさげ。
実行結果
ffffffff80000000
8000000000000000
ffffffff80000000
8000000000000000
逆アセンブル
Visual C++ 2010 Express Release 構成で最適化だけ無効化
(コンパイラさんが頑張りすぎて今回の記事にはそぐわないので)。
x86
; __int64 flags = 1 << rhs32; mov eax,1 mov ecx,dword ptr [rhs32] shl eax,cl cdq mov dword ptr [flags],eax mov dword ptr [ebp-14h],edx ; __int64 flags = static_cast<__int64>(1) << rhs32; mov eax,1 xor edx,edx mov ecx,dword ptr [rhs32] call _allshl mov dword ptr [flags],eax mov dword ptr [ebp-1Ch],edx
32bit版では、_allshlというサブルーチンの呼び出しになっている模様。
x64
; __int64 flags = 1 << rhs32; mov eax,dword ptr [rhs32] mov ecx,1 mov dword ptr [rsp+50h],ecx movzx ecx,al mov eax,dword ptr [rsp+50h] shl eax,cl cdqe mov qword ptr [flags],rax ; __int64 flags = static_cast<__int64>(1) << rhs32; mov eax,dword ptr [rhs32] mov ecx,1 mov qword ptr [rsp+58h],rcx movzx ecx,al mov rax,qword ptr [rsp+58h] shl rax,cl mov qword ptr [flags],rax
64bit版では、shl命令に。