怪异的右移位不一致

时间:2018-09-21 19:36:09

标签: c ubuntu bit-manipulation bit-shift

我一直在处理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

什么解释了这种行为?

2 个答案:

答案 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符合预期。