奇怪的右移位不一致

Bizarre right bitshift inconsistency

我一直在使用 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 并且它在转换期间回绕。当您对负数进行位移时,它会变得 weird.

如果您将这些值更改为 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),x 是 符号扩展 ,因此附加“1”导致 0xFFFFFFFF。

相反,

int b = 0xfffffffe >> 16;

0xfffffffe 是一个被解释为 无符号 整数的乱码。因此,逻辑 移位 16 结果如预期的那样为 0x0000FFFF。