0

When shift count < width of type, it works as expected:

int a = 1 << (8 * sizeof(int) - 1);
printf("%x\n", a); // 80000000

When shift count >= width of type, the result is different every time and there seems no law:

int b = 1 << 8 * sizeof(int); // int b = 1 << (8 * sizeof(int) + 1);
printf("%x\n", b); // such as 59fa2ba8, 5b0f6ba8, 52f46ba8 etc

Well, there is a warning saying warning: shift count >= width of type [-Wshift-count-overflow]. If this can explain the random outcome, then let me put the shift count into a variable:

int k = 8 * sizeof(int);
int c = 1 << k;
int d = 1 << (k + 1);
printf("%x\n", c); // 1
printf("%x\n", d); // 2

The result is totally different from before, this is Circular shift! How to explain this?

fujianjin6471
  • 5,168
  • 1
  • 36
  • 32
  • note that `1 << (8 * sizeof(int) - 1)` also causes undefined behaviour (one consequence of which may be appearing to work as expected). Further UB is caused by using the wrong format specifier, `int` requires `%d`. – M.M Jan 31 '16 at 05:16
  • @M.M Could you please give an example in which `1 << (8 * sizeof(int) - 1)` doesn't work as expected? – fujianjin6471 Jan 31 '16 at 05:59

1 Answers1

3
int b = 1 << 8 * sizeof(int);

is subject to undefined behavior.

From the C99 Standard:

6.5.7 Bitwise shift operators

3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. 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.

It's pointless to try to make sense of the outcome of such an operation.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • But how to explain the circular shift when I put the shift count into a variable? – fujianjin6471 Jan 31 '16 at 05:06
  • We can't make sense of what a compiler does in this case. What one compiler does will most likely be different than what another compiler does. Not only that, the behavior of the compiler could change if you change go from a debug build to a release build, or change optimization levels. – R Sahu Jan 31 '16 at 05:09
  • I see. But why doesn't make it a compile error? – fujianjin6471 Jan 31 '16 at 05:54
  • @fujianjin6471, the language has a lot of constructs that the language says is undefined behavior but still legal. It's up to a compiler to decide how to deal with such constructs. – R Sahu Jan 31 '16 at 05:57
  • And we should always avoid undefined behaviour to make our code more portable, right? – fujianjin6471 Jan 31 '16 at 06:02
  • @fujianjin6471, absolutely. – R Sahu Jan 31 '16 at 06:03