奇怪的右位移不一致

问题描述 投票:1回答:2

我一直在使用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

什么解释了这种行为?

c ubuntu bit-manipulation bit-shift
2个回答
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;
}

2
投票

您在此处看到的行为与移位有符号或无符号整数有关,这些整数会产生不同的结果。无符号整数的移位是合乎逻辑的。相反,有符号整数的移位是算术运算。编辑:在C中,它的实现已定义,但通常情况如此。

所以,

int x = 0xfffffffe;
int a = x >> 16;

由于x是有符号的,因此该部分执行算术移位。并且因为x实际上是负的(2的补码中的-2),所以x是符号扩展的,所以'1'被追加,导致0xFFFFFFFF。

反之,

int b = 0xfffffffe >> 16;

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

© www.soinside.com 2019 - 2024. All rights reserved.