q0987
q0987

Reputation: 35982

Why Left-Shifting an unsigned number 32 times doesn't produce a ZERO?

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

Upvotes: 6

Views: 1006

Answers (3)

6502
6502

Reputation: 114539

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

Upvotes: 1

Yu Hao
Yu Hao

Reputation: 122403

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.

Upvotes: 6

StilesCrisis
StilesCrisis

Reputation: 16290

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.

Upvotes: 14

Related Questions