Bitwise shift in C [duplicate]

こ雲淡風輕ζ 提交于 2019-12-07 08:12:39

问题


I got some C code that confuses me:

int a = 1;
int b = 32;
printf("%d\n %d\n", a<<b, 1<<32);

The output is

1
0

The code was run on Ubuntu 16.04 (Xenial Xerus), and I compiled it using gcc -m32 a.c with GCC version 5.4.0.

I've read some posts that have explained why a<<b outputs 1, but I don't understand why 1<<32 results to 0. I mean, what is the difference between a<<b and 1<<32?


回答1:


Shifting a 32-bit int left by 32 is undefined behavior, so any value could be produced as the result. Your C compiler should warn you about it in case of 1<<32 expression.

The reason the two outputs that you see are different is that they are produced by different code paths:

  • a << b uses variables, so it is computed at runtime by the compiled code
  • 1<<32 is a constant expression, so it is computed at compile time by the compiler itself

It looks like the compiled code performs the shift by modulo 32, so shift by 32 is the same as a shift by zero. The compiler itself, however, shifts by 32, dropping the one bit off the end. The compiler is free to do this, because this behavior is undefined. Hence, the standard does not demand any particular behavior, or even a consistent behavior among parts of the same program.




回答2:


a<<b and 1<<32 are undefined behaviour, because your right operand is equal to the number of bits.

C11 §6.5.7 Bitwise shift operators

Paragraph 3:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.The result is undefined if the right operand is negative, or greater than or equal to the number of bits in the left expression’s type.

Paragraph 4:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

So, if the number is shifted more than the size of integer, the behaviour is undefined.

GCC generated warning:

warning: left shift count >= width of type [-Wshift-count-overflow]
     printf("%d\n%d",a<<b,1<<32);



回答3:


Shifting by a constant value, versus shifting by b bits can result in different behavior under the rule that undefined behavior may be optimized out of existence. In other words, shifting by a constant value is probably optimized differently than shifting by a variable number of bits. Both are obviously undefined behavior so the compiler is free to handle either case any way it wishes. It could literally generate random numbers.




回答4:


Shifting signed values is dangerous and should be avoided.

If the size of the int is 32 bit, 1 << 31 is implementation dependent - two's complement = -2147483648. -1 << 31 gives the same result.

If you shift the value >= times that the number of bits the result is undefined.



来源:https://stackoverflow.com/questions/46769196/bitwise-shift-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!