-2

Can you please tell me how does why the following code gives a negative result due to the left shifting of an unsigned number a with a negative value?

    int main(void)
     {
          unsigned int a=1;
          printf("%d",a<<-1);   

     }

Output -2147483648.

Rüppell's Vulture
  • 3,583
  • 7
  • 35
  • 49
Maddy
  • 503
  • 4
  • 12
  • 21

2 Answers2

5

From this article:

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.

So what you are doing is undefined behavior. Don't shift a negative number of bits if you want predictable behavior.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Beside the fact that this is undefined behavior we can try to consider what happen in your case. But beware, this depends also on the compiler and the underlying machine. In this answer Im using VC++ 2010 on an x86 machine.

Take a look at the code

#include "stdafx.h"

int main(int argc, _TCHAR* argv[])
{
    unsigned int a  = 1;
    printf("%d",a<<-1);   

    a  = 1;
    printf("%d",a<<31);   
}

Both shifts give the same answer. To see what happen we need to take a look to the disassembly in this case.

010E1A4E  mov         dword ptr [a],1  
010E1A55  mov         eax,dword ptr [a]  
010E1A58  shl         eax,0FFh  
...

010E1A73  mov         dword ptr [a],1  
010E1A7A  mov         eax,dword ptr [a]  
010E1A7D  shl         eax,1Fh  
...

The negativ shift is compiled to shl eax, 0ffh. For the x86 the displacement of the shift instruction can only be 8bit thats the reason why the compiler here using (-1 & 0xff) = 0xff. But the instruction itself will mask this constant by 0x1f. Therefore both shifts have the same result. After execution of the shift the result will be 0x80000000 which is as integer (please note you use %d in printf) the same as -2147483648.

David J
  • 1,554
  • 9
  • 15