为什么将 int a=1 向左移动 31 位然后向右移动 31 位,它变成 -1
why shift int a=1 to left 31 bits then to right 31 bits, it becomes -1
给定
int a = 1;
(00000000000000000000000000000001
),
我所做的只是
a=(a<<31)>>31;
我假设 a
在此声明之后仍应为 1
(我认为没有任何变化)。然而,结果却是-1
(11111111111111111111111111111111
)。任何人都知道为什么?
" however it turns out to be -1
"
您使用 unsigned int
这样做是为了仅查看大于 0
的 32 位值:
unsigned int a = 1;
a=(a<<31)>>31;
这是一个带符号的移位,所以最左边的位将被扩展。这样总数就在0的同一边了。
通过向左移动那么多,您将最低位放入符号位并以负数结尾。
然后当您右移时,它会扩展符号,将符号位向下复制到低 31 位。
如果你想知道最低位就做& 1
.
您缺少的是在 C++ 中右移 >>
是实现定义的。对于有符号值,它可以是逻辑移位或算术移位。在这种情况下,它从左侧移动 1
s 以保留移动值的符号。通常,您希望避免对有符号值进行移位,除非您确切地知道它们将是正数或者移位实施无关紧要。
分步看:
#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
,您将获得预期的行为。
给定
int a = 1;
(00000000000000000000000000000001
),
我所做的只是
a=(a<<31)>>31;
我假设 a
在此声明之后仍应为 1
(我认为没有任何变化)。然而,结果却是-1
(11111111111111111111111111111111
)。任何人都知道为什么?
" however it turns out to be
-1
"
您使用 unsigned int
这样做是为了仅查看大于 0
的 32 位值:
unsigned int a = 1;
a=(a<<31)>>31;
这是一个带符号的移位,所以最左边的位将被扩展。这样总数就在0的同一边了。
通过向左移动那么多,您将最低位放入符号位并以负数结尾。
然后当您右移时,它会扩展符号,将符号位向下复制到低 31 位。
如果你想知道最低位就做& 1
.
您缺少的是在 C++ 中右移 >>
是实现定义的。对于有符号值,它可以是逻辑移位或算术移位。在这种情况下,它从左侧移动 1
s 以保留移动值的符号。通常,您希望避免对有符号值进行移位,除非您确切地知道它们将是正数或者移位实施无关紧要。
分步看:
#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
,您将获得预期的行为。