为什么将a = 1向左移31位然后向右移31位,它变为-1

时间:2015-04-23 23:25:38

标签: c++ bit-manipulation

给出

int a = 1;00000000000000000000000000000001),

我所做的只是

a=(a<<31)>>31;

我认为a在此声明之后仍应为1(我认为没有任何改变)。但是,结果是-111111111111111111111111111111111)。谁知道为什么?

4 个答案:

答案 0 :(得分:5)

你缺少的是在C ++中,右移>>是实现定义的。它可以是有符号值的逻辑或算术移位。在这种情况下,它从左侧1移位以保留移位值的符号。通常,您希望避免对签名值进行转换,除非您确切知道它们是正面的,或者转换实现并不重要。

答案 1 :(得分:3)

分步观察:

#include <cstdio>
using namespace std;

int main()
{
    int a = 1;
    printf("%d = %x\n", a, a);
    a <<= 31;
    printf("%d = %x\n", a, a);
    a >>= 31;
    printf("%d = %x\n", a, a);
    return 0;
}

输出:

1 = 1
-2147483648 = 80000000
-1 = ffffffff

1一直向上移动到高位,这使得它成为负数。向下移动会触发符号扩展以维持负面。

将a的声明更改为unsigned int a,您将获得所期望的行为。

答案 2 :(得分:1)

  

“然而事实证明是-1

您只使用unsigned int来查看大于0的32位值:

 unsigned int a = 1; 
 a=(a<<31)>>31;  

答案 3 :(得分:0)

这是一个有符号的移位,因此最左边的位将被扩展。这样整体数字就在0的同一侧。

通过向左移动那么多,你将最低位置于符号位并以负数结束。

当你进行右移时,它的符号会扩展,将符号位向下复制到低31位。

如果您想知道最低位,请执行& 1