为什么会(-1 >> 1)导致-1?我在C工作,虽然我认为这不重要.
我无法弄清楚我错过了什么......
以下是执行计算的C程序示例:
#include <stdio.h>
int main()
{
int num1 = -1;
int num2 = (num1 >> 1);
printf( "num1=%d", num1 );
printf( "\nnum2=%d", num2 );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*one 23
因为有符号整数用二进制补码表示.
-1将11111111(如果它是一个8位数字).
-1 >> 1显然标志延伸,以便它仍然存在11111111.这种行为取决于编译器,但对于Microsoft,当右移(#(>>)符号位时,符号位被复制,而右移无符号数会导致a 0被置于最左边的位.
Wad*_* M. 11
11111111 (-1) will stay 11111111 (-1)
Run Code Online (Sandbox Code Playgroud)
相反,逻辑右移不会保留标志:
11111111 (-1) will become 01111111 (127)
Run Code Online (Sandbox Code Playgroud)
您的代码清楚地执行算术移位,因此重复符号位(MSB).运算符(>>)的作用取决于您正在使用的平台的实现细节.在大多数情况下,这是算术转换.
另外,请注意,11111111根据表示,可以有两种不同的含义.这也会影响他们的转变方式.
11111111表示255.向右移动不会保留符号,因为MSB不是符号位.11111111表示-1.算术上将它向右移动将保留标志.位移负数是C中的实现行为.结果取决于您的平台,理论上可能完全没有意义.从C99标准(6.5.7.5):
E1 >> E2的结果是E1右移E2位位置.如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1/2 ^ E2的商的整数部分.如果E1具有有符号类型和负值,则生成的值是实现定义的.
发生这种情况的原因很可能是因为您的编译器使用x86 SAR(Shift Arithmetic Right)指令来实现>>.这意味着将发生符号扩展 - 一旦值被移位,最高有效位将被复制到新的MSB中.来自intel手册:
移位算术右(SAR)和移位逻辑右(SHR)指令将目标操作数的位向右移位(朝向不太重要的位位置).对于每个移位计数,目标操作数的最低有效位被移入CF标志,并且根据指令类型设置或清除最高有效位.SHR指令清除最重要的位(参见英特尔®64和IA-32架构软件开发人员手册第1卷中的图7-8); SAR指令设置或清除最高有效位以对应于目标操作数中原始值的符号(最高有效位).实际上,SAR指令使用未移位值的符号填充空位位置的移位值(请参阅"英特尔®64和IA-32架构软件开发人员手册"第1卷中的图7-9).