Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does bit-shifting an int upwards produce a negative number?

I am new to bit manipulations tricks and I wrote a simple code to see the output of doing single bit shifts on a single number viz. 2

#include <iostream>
int main(int argc, char *argv[])
{

  int num=2;

 do
   {
     std::cout<<num<<std::endl;
     num=num<<1;//Left shift by 1 bit.

   } while (num!=0);


  return 0;
}

The output of this is the following.

2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
-2147483648

Obviously, continuously bit shifting to the left by 1 bit, will result in zero as it has done above, but why does the computer output a negative number at the very end before terminating the loop (since num turned zero)??

However when I replace int num=2 by unsigned int num=2 then I get the same output except that the last number is this time displayed as positive i.e. 2147483648 instead of -2147483648

I am using the gcc compiler on Ubuntu Linux

like image 901
smilingbuddha Avatar asked Dec 03 '11 22:12

smilingbuddha


People also ask

What happens when you bit shift a negative number?

For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used. The result of a right-shift of a signed negative number is implementation-dependent.

What happens when you shift a bit?

A bit-shift moves each digit in a number's binary representation left or right. Within right-shifts, there are two further divisions: logical right-shift and arithmetic right-shift. A left-shift is represented by the << operator, while a right-shift is represented by the >> operator.

Why might Left shifting a negative integer give an undefined result?

The left shift and right shift operators should not be used for negative numbers. The result of is undefined behaviour if any of the operands is a negative number. For example results of both 1 >> -1 and 1 << -1 is undefined. If the number is shifted more than the size of integer, the behaviour is undefined.

Is shifting right negative or positive?

A negative value indicates a shift to the right, and a positive value indicates a shift to the left. A vertical shift is a change in the y-intercept, or b-value.


1 Answers

That's because int is a signed integer. In the two's-complement representation, the sign of the integer is determined by the upper-most bit.

Once you have shifted the 1 into the highest (sign) bit, it flips negative.

When you use unsigned, there's no sign bit.

0x80000000 = -2147483648 for a signed 32-bit integer.
0x80000000 =  2147483648 for an unsigned 32-bit integer.

EDIT :

Note that strictly speaking, signed integer overflow is undefined behavior in C/C++. The behavior of GCC in this aspect is not completely consistent:

  • num = num << 1; or num <<= 1; usually behaves as described above.
  • num += num; or num *= 2; may actually go into an infinite loop on GCC.
like image 102
Mysticial Avatar answered Sep 23 '22 04:09

Mysticial