This is a 32-bit MFC application currently running on Windows 10. Compiled with Visual C++ 2013.
std::cout << "sizeof(long long) = " << sizeof(long long) << std::endl;
int rot{ 32 };
long long bits{ (1 << rot) };
std::cout << "bits with variable = " << bits << std::endl;
long long bits2 = (1 << 32);
std::cout << "bits2 with constant = " << bits2 << std::endl;
system("pause");
The size of long long is 8 bytes, sufficient to manage my 32 bits, I was thinking. Here is the output of the debug build:
sizeof(long long) = 8
bits with variable = 1
bits2 with constant = 0
Press any key to continue . . .
And here is the output of the release build:
sizeof(long long) = 8
bits with variable = 0
bits2 with constant = 0
Press any key to continue . . .
So, apparently my single bit is leftshifted into oblivion even with a 64 bit data type. But I'm really puzzled to why the debug build produces different outputs if I shift with a variable as a parameter compared to a constant?
The expression 1 << rot
, when rot
is an int
, will give you an int
result. It doesn't matter if you then place it into a long long
since the damage has already been done(a).
Use 1LL << rot
instead.
(a) And, by damage, I mean undefined behaviour, as per C11 6.5.7 Bitwise shift operators
:
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
As to "why the debug build produces different outputs if I shift with a variable as a parameter compared to a constant", that's one of the vagaries of undefined behaviour - literally anything that's possible is allowed to happen. It's perfectly within its rights to play derisive_laughter.ogg
and format your hard disk :-)