我一直在处理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
什么解释了这种行为?
答案 0 :(得分:4)
当你说:
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;
}
答案 1 :(得分:2)
您在此处看到的行为与对有符号或无符号整数进行移位有关,这会产生不同的结果。 无符号整数的移位是逻辑。相反,有符号整数的移位是算术。 编辑:在C语言中,它是实现的定义,但通常是这种情况。
因此,
int x = 0xfffffffe;
int a = x >> 16;
这部分执行算术移位,因为x是 signed 。而且由于x实际上是负数(二进制补码为-2),所以x是符号扩展,因此附加了“ 1”,结果为0xFFFFFFFF。
相反,
int b = 0xfffffffe >> 16;
0xfffffffe是乱码,其解释为 unsigned 整数。因此,逻辑的移位为16会导致0x0000FFFF符合预期。