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命令に。

余談

整数リテラルで末尾にLを付けた場合は64bit整数リテラルになるとずっと思い込んでいた…恥ずかしいorz
実際はlong型の整数リテラルになる。