我一直在使用C中的位(在ubuntu上运行)。在使用两种不同的方式右移一个整数时,我得到了奇怪的不同输出:
#include <stdio.h>
int main(){
int x = 0xfffffffe;
int a = x >> 16;
int b = 0xfffffffe >> 16;
printf("%X\n%X\n", a, b);
return 0;
}
我认为每个输出都是相同的:FFFF,因为正确的四个十六进制位置(16位)正在被移除。相反,输出是:
FFFFFFFF
FFFF
什么解释了这种行为?
当你说:
int x = 0xfffffffe;
这将x
设置为-2,因为int
在这里可以容纳的最大值是0x7FFFFFFF
并且它在转换期间包裹。当您对负数进行位移时,它会变得奇怪。
如果你将这些值更改为unsigned int
,那一切都可以解决。
#include <stdio.h>
int main(){
unsigned int x = 0xfffffffe;
unsigned int a = x >> 16;
unsigned int b = 0xfffffffe >> 16;
printf("%X\n%X\n", a, b);
return 0;
}
您在此处看到的行为与移位有符号或无符号整数有关,这些整数会产生不同的结果。无符号整数的移位是合乎逻辑的。相反,有符号整数的移位是算术运算。编辑:在C中,它的实现已定义,但通常情况如此。
所以,
int x = 0xfffffffe;
int a = x >> 16;
由于x是有符号的,因此该部分执行算术移位。并且因为x实际上是负的(2的补码中的-2),所以x是符号扩展的,所以'1'被追加,导致0xFFFFFFFF。
反之,
int b = 0xfffffffe >> 16;
0xfffffffe是一个被解释为无符号整数的litteral。因此,16的逻辑移位导致0x0000FFFF如预期的那样。