Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 奇怪的右位移位不一致_C_Ubuntu_Bit Manipulation_Bit Shift - Fatal编程技术网

C 奇怪的右位移位不一致

C 奇怪的右位移位不一致,c,ubuntu,bit-manipulation,bit-shift,C,Ubuntu,Bit Manipulation,Bit Shift,我一直在使用C语言中的bits(在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; } 是什么解释了这种行为?当你说: int x = 0xfffffffe; 这将x设置

我一直在使用C语言中的bits(在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;
}
是什么解释了这种行为?

当你说:

int x = 0xfffffffe;
这将
x
设置为-2,因为
int
可以在这里保存的最大值是
0x7fffff
,并且在转换过程中它会缠绕。当你移位负数时,它会变得很奇怪

如果您将这些值更改为
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;
}
#包括
int main(){
无符号整数x=0xfffffffe;
无符号整数a=x>>16;
无符号整数b=0xFFFFFE>>16;
printf(“%X\n%X\n”,a,b);
返回0;
}
当你说:

int x = 0xfffffffe;
这将
x
设置为-2,因为
int
可以在这里保存的最大值是
0x7fffff
,并且在转换过程中它会缠绕。当你移位负数时,它会变得很奇怪

如果您将这些值更改为
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;
}
#包括
int main(){
无符号整数x=0xfffffffe;
无符号整数a=x>>16;
无符号整数b=0xFFFFFE>>16;
printf(“%X\n%X\n”,a,b);
返回0;
}

您在这里看到的行为与有符号或无符号整数的移位有关,这会产生不同的结果。 无符号整数上的移位是逻辑的。相反,有符号整数上的移位是算术运算EDIT:在C语言中,它是实现定义的,但通常情况下是这样的

因此,

int x = 0xfffffffe;
int a = x >> 16;
这部分执行算术移位,因为x是有符号的。因为x实际上是负数(-2在2的补码中),所以x是符号扩展的,所以附加了'1',结果是0xFFFFFF

相反,

int b = 0xfffffffe >> 16;

0xFFFFFE是一个通常解释为无符号整数的小整数。因此,16的逻辑移位会产生预期的0x0000FFFF。

您在这里看到的行为与有符号或无符号整数的移位有关,这会产生不同的结果。 无符号整数上的移位是逻辑的。相反,有符号整数上的移位是算术运算EDIT:在C语言中,它是实现定义的,但通常情况下是这样的

因此,

int x = 0xfffffffe;
int a = x >> 16;
这部分执行算术移位,因为x是有符号的。因为x实际上是负数(-2在2的补码中),所以x是符号扩展的,所以附加了'1',结果是0xFFFFFF

相反,

int b = 0xfffffffe >> 16;

0xFFFFFE是一个通常解释为无符号整数的小整数。因此,16的逻辑移位会产生预期的0x0000FFFF。

如果进行位运算,通常应使用无符号类型。如果进行位运算,则通常应使用无符号类型。值得注意的是,它无法保持的值的
signed int
转换是由实现定义的。@EugeneSh。说得好。我敢肯定,打开了攻击性警告的优秀编译器也会对此感到震惊。这并不像实现定义的那样“怪异”。大多数实现在右移时执行“符号扩展”——也就是说,“空出的”MSB保持不变,因此值的符号保持不变。一些实现可能会用零填充空的指令集,这通常取决于机器指令集是否有算术右移指令,而不是逻辑右移指令。对于同时具有这两种功能的处理器,如x86,使用算术移位是有意义的,但它不是给定的。@Clifford这是一个很好的解释,也是我所说的“怪异”的一个长格式版本。值得注意的是,它不能保持的值的
有符号int
的转换是实现定义的。@EugeneSh。说得好。我敢肯定,打开了攻击性警告的优秀编译器也会对此感到震惊。这并不像实现定义的那样“怪异”。大多数实现在右移时执行“符号扩展”——也就是说,“空出的”MSB保持不变,因此值的符号保持不变。一些实现可能会用零填充空的指令集,这通常取决于机器指令集是否有算术右移指令,而不是逻辑右移指令。对于具有这两种功能的处理器,如x86,使用算术移位是有意义的,但它不是给定的。@Clifford这是一个很好的解释,也是我所说的“怪异”的一个长形式版本。在C中,根据C 2018 6.5.7 5定义的负值实现上的右移位行为。在C中,根据C 2018 6.5.7 5,定义了负值实施时右移的行为。