2

I'm debugging some code and came across some behavior I cannot explain.

I am trying to shift the number -1 to the left 32 times to produce a zero in this particular case.

int n = 0;
int negOne = ~0;
int negativeN = ( (~n) + 1 );
int toShift = (32 + negativeN);   //32 - n

/*HELP!!! These produce two different answers*/
printf("%d << %d = %d \n",negOne, toShift, negOne << toShift);
printf("-1 << 32 = %d \n", -1 << 32) ;

Here is the what the console outputs:

-1 << 32 = -1 
-1 << 32 = 0 

I am not sure why the left shift is behaving differently in each of these cases.

hededo
  • 371
  • 2
  • 16
  • 3
    This is usually a sign of undefined behaviour. – juanchopanza Sep 02 '14 at 06:25
  • 1
    [Coincidental question](https://stackoverflow.com/questions/25611903/unexpected-behavior-while-dealing-with-shift-operators). Related to [this question](http://stackoverflow.com/questions/11270492/what-does-the-c-standard-say-about-bitshifting-more-bits-than-the-width-of-type). – WhozCraig Sep 02 '14 at 06:30

2 Answers2

3

It's undefined behavior because you shift count is bigger than the number of bits for an int, that means that the result can't be predicted.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    It is also UB because the left operand is signed (see duplicate linked above.) – juanchopanza Sep 02 '14 at 06:30
  • 1
    bigger than or **equal to**, in this example, they are equal ;) – Yu Hao Sep 02 '14 at 06:31
  • 2
    To clarify juanchopanza's point, if the left operand were unsigned, the result *would* be defined. The behavior is undefined only when the left operand is signed and the arithmetic value of the shift is not representable. For details see http://stackoverflow.com/a/22883850/2611123 – Chris Culter Sep 02 '14 at 06:33
  • @ChrisCulter it would still be undefined if the left operand were unsigned. – M.M Sep 02 '14 at 06:48
2

When you Shift a number equal to or more than the number of its bit times your result can't be predictable! Simply it is Undefined_behavior.

If you compile your program with flags you will get warning for this shifting

Sathish
  • 3,740
  • 1
  • 17
  • 28
  • 1
    To be precise, this is true for signed integer types, but not for unsigned types; see http://stackoverflow.com/a/22883850/2611123 – Chris Culter Sep 02 '14 at 06:35
  • @ChrisCulter you're looking at the wrong clause; shifting by the width of the type (or more) is undefined for all types. – M.M Sep 02 '14 at 06:47
  • @MattMcNabb I'm afraid I disagree; this sentence seems pretty clear: "If E1 has an unsigned type, the value of the result is E1 × 2^(E2), reduced modulo one more than the maximum value representable in the result type." – Chris Culter Sep 02 '14 at 07:02
  • @MattMcNabb Hmm, that section number and that language don't exist in [C99 + TC1 + TC2 + TC3](http://www.open-std.org/jtc1/sc22/wg14/www/standards). Are you quoting a C++ standard? – Chris Culter Sep 02 '14 at 07:12
  • @ChrisCulter Sorry, C11 (n1570) 6.5.7/3 "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." Similar (or identical) text is in C99 and C89. It's about an inch above the text you quoted (depending on your screen size) – M.M Sep 02 '14 at 07:15
  • @MattMcNabb Oh! I see, the conditions in that paragraph are meant to apply before the following paragraphs. My mistake, thanks for the correction! – Chris Culter Sep 02 '14 at 07:18