6
#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?

StilesCrisis
  • 15,972
  • 4
  • 39
  • 62
q0987
  • 34,938
  • 69
  • 242
  • 387
  • 1
    possible duplicate of [Why doesn't left bit-shift, "<<", for 32-bit integers work as expected when used more than 32 times?](http://stackoverflow.com/questions/7401888/why-doesnt-left-bit-shift-for-32-bit-integers-work-as-expected-when-used) – Daniel Frey Sep 13 '13 at 16:22

3 Answers3

14

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.

StilesCrisis
  • 15,972
  • 4
  • 39
  • 62
  • "I believe only the low 5 bits of the shift amount are used by the CPU". What do you mean by that? Given a 32-bit int, only `intI << 4`is valid???? – q0987 Sep 13 '13 at 16:27
  • 2
    @q0987, it means that the upper bits of the shift amount are ignored - 32 is the same as 0 for specifying the number of bits to shift. – Mark Ransom Sep 13 '13 at 16:33
  • 1
    Another way of saying it is that `intI << X` is the same as `intI << (X & 0x1F)` because that how the hardware is (in some cases) going to handle it. – IronMensan Sep 13 '13 at 18:25
  • Right. The most important part is to understand is that not all hardware interprets it that way; other hardware might see it as (intI << (X & 0x3F)) or just ignore the shift entirely. The standard allows for literally any behavior, even a crash. – StilesCrisis Sep 13 '13 at 18:45
6

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.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
1

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

6502
  • 112,025
  • 15
  • 165
  • 265