2009-06-26 134 views
7

为什么(-1 >> 1)结果-1?我在C工作,但我认为这不重要。(-1 >> 1)== -1 - 为什么?

我想不通,我错过了什么?

这里是一个C程序,它的计算的一个例子:

#include <stdio.h> 



int main() 
{ 
    int num1 = -1; 

    int num2 = (num1 >> 1); 

    printf("num1=%d", num1); 

    printf("\nnum2=%d", num2); 

    return 0; 
} 
+1

在php“echo -1 >> 1中也是如此;” – merkuro 2009-06-26 01:42:57

+0

也在python中,正如答案所说,负数填充1以保留符号是有意义的。 – 2009-06-26 01:45:40

回答

23

由于带符号整数表示为two's complement表示法。

-111111111(如果它是一个8位的数字)。

-1 >> 1显然符号扩展,使之保持11111111。这种行为取决于编译器,但对于Microsoft,在移位有符号数字权限(>>)时复制符号位,而移动无符号数字权限会导致0被置于最左边的位。

5

位移负数是C.执行行为的结果将取决于你的平台上,理论上可能是完全荒谬的。从C99的标准(6.5.7.5):

E1 >> E2的结果是E1 右移E2位的位置。如果E1 具有无符号类型或者如果E1具有 有符号型和非负值,则 结果的值是 E1/ 2^E2的商的整数部分。如果E1具有带符号的类型和 负值,则结果值为 实现定义。

发生这种情况的原因很可能是因为您的编译器使用x86 SAR(Shift Arithmetic Right)指令来实现>>。这意味着会发生符号扩展 - 一旦数值被移位,最重要的位将被复制到新的MSB中。从intel manuals

移位算术右移(SAR)和 移位逻辑右(SHR)的指令 目的地 操作数的比特移位到右侧(朝向更少 显著位位置)。对于每个 移位计数,目标操作数的最低有效位 将 移位到CF标志中,并且最重要的位为 或者 取决于指令 类型。在SHR指令清除 最显著位(见图7-8 在64和IA-32 架构软件开发人员 手册,卷1); SAR指令 设置或清除最显著 比特以对应于所述目的地操作数的原始值 的符号(最 显著位)。 实际上, SAR指令填充所述空 比特位置与未移位值的 符号(参见 图7-9中的64和IA-32 架构软件开发人员 手册,第1卷移位值)。

+1

引用的段落指出像(10 >> -1)这样的操作未定义。右操作数是-1。 – rlbond 2009-06-26 01:46:45

3

当你右移并且最左边的位是1时,一些平台/编译器将带入0,并且一些将保留1并且使新的最左边的位成为1.这保留了数字的符号,所以是负数号码保持负面并被称为符号扩展。

如果您尝试((unsigned) -1) >> 1,您会看到区别,它会执行无符号的右移,因此总是会移入0位。

11

Arithmetic right shift一个移位signed number时将保留符号:

11111111 (-1) will stay 11111111 (-1) 

相反,Logical right shift将不保留符号:

11111111 (-1) will become 01111111 (127) 

您的代码清楚地做算术移位,所以重复符号位(MSB)。操作符(>>)的功能取决于您使用的平台的实现细节。在大多数情况下,这是一个算术转换。

此外,请注意11111111可以有两种不同的含义,具体取决于表示形式。这也影响到他们将被转移的方式。

  • 如果没有符号,11111111代表255它向右移动将不保留迹象,因为MSB是不是一个符号位。
  • 如果有符号,11111111代表-1。在算术上将它移到右边将保留标志。
相关问题