#include <iostream>
using namespace std;
int main()
{
cout << "sizeof(unsigned int): " << sizeof(unsigned int) << endl;
unsigned a = 1;
int i = 0;
while (a) {
cout << "a[" << i++ << "]: " << a << endl;
a <<= 1;
}
cout << "a[" << i << "]: " << a << endl;
unsigned b = 1;
unsigned c = (b << 31);
unsigned d = (b << 32);
cout << "c: " << c << endl;
cout << "d: " << d << endl;
return 0;
}
/* Output http://www.compileonline.com/compile_cpp_online.php */
Compiling the source code....
$g++ main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
main.cpp: In function 'int main()':
main.cpp:19:23: warning: left shift count >= width of type [enabled by default]
Executing the program....
$demo
sizeof(unsigned int): 4
a[0]: 1
a[1]: 2
a[2]: 4
a[3]: 8
a[4]: 16
a[5]: 32
a[6]: 64
a[7]: 128
a[8]: 256
a[9]: 512
a[10]: 1024
a[11]: 2048
a[12]: 4096
a[13]: 8192
a[14]: 16384
a[15]: 32768
a[16]: 65536
a[17]: 131072
a[18]: 262144
a[19]: 524288
a[20]: 1048576
a[21]: 2097152
a[22]: 4194304
a[23]: 8388608
a[24]: 16777216
a[25]: 33554432
a[26]: 67108864
a[27]: 134217728
a[28]: 268435456
a[29]: 536870912
a[30]: 1073741824
a[31]: 2147483648
a[32]: 0
c: 2147483648
d: 1
Question> As you can see a[32
is equal to 0. Now why d
is NOT 0
but 1
?
This is undefined behavior in C/C++.
The standard specifically leaves this undefined because different CPUs will do different things when presented with such a shift. Specifically, on 32-bit Intel, I believe only the low 5 bits of the shift amount are used by the CPU, and the rest of the bits are just ignored. If I remember correctly, PowerPC and 64-bit Intel both use the low 6 bits and ignore the rest.
A higher level language might attempt to smooth this out by correcting the results to be more logically consistent, but a low-level language like C/C++ is designed to be "close to the metal" and will want to generate a single bit-shift instruction for the <<
operator.
b << 32
is undefined behavior because the size of b
(unsigned int
) is 32-bit in your machine.
C++11 §5.8 Shift operators
The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.
It's a limitation of the language.
To help mapping <<
and >>
directly to machine language instructions the language inherits the hardware limitations where shift counts that are negative or bigger than the register size are often not doing what you'd expect.
For example it would be nice also to have
15 << -1
to mean the same as
15 >> 1
but unfortunately this is not the case
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With