【问题标题】:why shift int a=1 to left 31 bits then to right 31 bits, it becomes -1为什么将 int a=1 向左移动 31 位然后向右移动 31 位,它变为 -1
【发布时间】:2015-04-23 23:25:38
【问题描述】:

给定

int a = 1; (00000000000000000000000000000001),

我所做的只是

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

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

【问题讨论】:

  • 查找符号扩展。然后用 unsigned int 再试一次。
  • 如果 'unsigned int a=1' 一切正常
  • 那个答案指的是运算符&gt;&gt;&gt;,它绝对不是C++运算符,所以我不认为它是重复的。
  • @ShaneNian 为什么你一直回滚我的编辑,这改进了你的问题格式?
  • 假设 2³¹ 可以用unsigned 表示,但不能用int 表示,即使a&lt;&lt;31 是实现定义的结果,甚至在右移开始发挥作用之前。

标签: c++ bit-manipulation


【解决方案1】:

您缺少的是在 C++ 中右移 &gt;&gt; 是实现定义的。它可以是有符号值的逻辑或算术移位。在这种情况下,它从左侧移入1s 以保留移位值的符号。通常,您希望避免对有符号值进行移位,除非您确切知道它们将是正数或者移位实现无关紧要。

【讨论】:

  • 1 &lt;&lt; 31 也是实现定义的 (ref)
【解决方案2】:

分步看:

#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,您将获得您所期望的行为。

【讨论】:

    【解决方案3】:

    " 但是它原来是-1"

    您使用 unsigned int 这样做是为了只查看大于 0 的 32 位值:

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

    【讨论】:

      【解决方案4】:

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

      通过左移这么多,您将最低位放入符号位并以负数结束。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-20
        • 2014-11-29
        • 2012-02-19
        • 2013-09-01
        • 1970-01-01
        • 2016-03-26
        相关资源
        最近更新 更多