(-1>> 1)== -1 - 为什么?

时间:2009-06-26 01:33:50

标签: c bit-shift

为什么(-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;
}

5 个答案:

答案 0 :(得分:23)

因为有符号整数用two's complement表示法表示。

-1将为11111111(如果是8位数字)。

-1 >> 1显然会签名延伸,以便保持11111111。此行为取决于编译器,但对于Microsoft,当向右移位有符号数字(>>)时,将复制符号位,而向右移位无符号数会导致0被置位在最左边的位。

答案 1 :(得分:11)

转换Arithmetic right shift后,signed number会保留标志:

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

相反,Logical right shift不会保留标志:

11111111 (-1) will become 01111111 (127)

您的代码显然会进行算术移位,因此重复符号位(MSB)。运算符(&gt;&gt;)的作用取决于您正在使用的平台的实现细节。在大多数情况下,这是算术转换。

另请注意,11111111可能有两种不同的含义,具体取决于表示形式。这也影响了他们的转变方式。

  • 如果无符号,11111111代表255.向右移动将不会保留符号,因为MSB不是符号位。
  • 如果签名,11111111代表-1。算术上将它向右移动将保留标志。

答案 2 :(得分:5)

将负数移位是C中的实现行为。结果将取决于您的平台,理论上可能完全没有意义。根据C99标准(6.5.7.5):

  

E1&gt;的结果&gt; E2是E1   右移E2位位置。如果E1   有一个无符号类型或E1有一个   签名类型和非负值,   结果的值是   E1 /的商的组成部分   2 ^ E2。如果E1有签名类型和   负值,结果值是   实施德音响定义

发生这种情况的原因很可能是因为您的编译器使用x86 SAR(Shift算术右)指令来实现&gt;&gt;。这意味着将发生符号扩展 - 一旦值被移位,最高有效位将被复制到新的MSB中。来自intel manuals

  

移位算术权(SAR)和   移位逻辑右(SHR)指令   移动目的地的位   操作数向右(朝向更少   重要的位置)。对于每一个   移位计数,最低有效位   目标操作数的移位   进入CF旗帜,最多   有效位是设置或   根据指示清除   类型。 SHR指令清除了   最重要的位(见图7-8   在英特尔®64和IA-32中   架构软件开发人员   手册,第1卷); SAR指令   设置或清除最重要的   位对应于符号(大多数   有意义的原始值   在目标操作数中。 实际上,   SAR指令填空   位位置的移位值   未移位价值的标志(见   图64中的Intel®64和IA-32   架构软件开发人员   手册,第1卷)。

答案 3 :(得分:3)

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

如果你尝试((unsigned) -1) >> 1,你会看到差异,它将进行无符号右移,因此总是会移位0位。

答案 4 :(得分:1)

签署延期。