代码之家  ›  专栏  ›  技术社区  ›  Frank V

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

  •  7
  • Frank V  · 技术社区  · 16 年前

    为什么 (-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 回复  |  直到 16 年前
        1
  •  23
  •   David Johnstone    16 年前

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

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

    -1 >> 1 显然,这个符号延伸到它仍然存在 一千一百一十一万一千一百一十一 . 这种行为取决于编译器,但是 Microsoft ,右移有符号数字时( >> )符号位被复制,同时向右移动一个无符号数字会导致 0 放在最左边。

        2
  •  11
  •   Wadih M.    16 年前

    Arithmetic right shift 移动时将保留标志 signed number :

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

    相比之下,A Logical right shift 不会保留标志:

    11111111 (-1) will become 01111111 (127)
    

    您的代码显然执行算术移位,因此符号位( MSB 重复。运营商(>>)所做的操作取决于所使用平台的实现细节。在大多数情况下,这是一个算术移位。

    另外,请注意 11111111 可以有两种不同的含义,这取决于表示。这也会影响它们的移动方式。

    • 如果未签名, 一千一百一十一万一千一百一十一 表示255。将其右移不会保留符号,因为MSB不是符号位。
    • 如果签署, 一千一百一十一万一千一百一十一 代表- 1。算术上把它右移会保留这个符号。
        3
  •  5
  •   bdonlan    16 年前

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

    e1的结果是e1 右移E2位。如果E1 具有无符号类型或如果e1具有 有符号类型和非负值, 结果的值是 e1商的整数部分/ 2 ^ E2。如果e1有符号类型和 负值,得到的值为 实施。

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

    右移算术(sar)和 移位逻辑右(SHR)指令 移动目的地的位 右侧的操作数(朝下 有效位位置)。对于每一个 移位计数,最低有效位 目标操作数的移动 进入CF标志,最 有效位设置为或 根据指示清除 类型。SHR指令清除 最高有效位(见图7-8 在Intel_64和IA-32中 架构软件开发人员 手册,第1卷);SAR说明 设置或清除最重要的 与符号相对应的位(大多数 原始值的有效位) 在目标操作数中。 实际上, sar指令填充空的 位位置_s移位值 非移位值的符号 (见 Intel_64和IA-32中的图7-9 架构软件开发人员 手册,第1卷)。

        4
  •  3
  •   John Kugelman Michael Hodel    16 年前

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

    如果你尝试,你会发现不同 ((unsigned) -1) >> 1 ,它将执行无符号右移,因此始终以0位移动。

        5
  •  1
  •   smcameron    16 年前

    符号扩展。