給出爲什麼轉變INT A = 1至左31位,然後向右31位,成爲-1
int a = 1;
(00000000000000000000000000000001
),
我所做的只是
a=(a<<31)>>31;
我假設a
應該仍然是1
之後(我認爲沒有什麼改變)。然而,它結果是-1
(11111111111111111111111111111111
)。有人知道爲什麼
給出爲什麼轉變INT A = 1至左31位,然後向右31位,成爲-1
int a = 1;
(00000000000000000000000000000001
),
我所做的只是
a=(a<<31)>>31;
我假設a
應該仍然是1
之後(我認爲沒有什麼改變)。然而,它結果是-1
(11111111111111111111111111111111
)。有人知道爲什麼
你缺少的是在C++右移>>
是實現定義的。它可以是有符號值的邏輯或算術平移。在這種情況下,它將從左側移動1
以保留移位值的符號。通常情況下,您希望避免在已簽名的值上進行轉換,除非您確切知道他們會是積極的或者轉換實施無關緊要。
'1 << 31'也是實現定義的([ref](https:// stackoverflow。COM /問題/ 26331035 /爲什麼 - 是-1-31-改變將要-實現定義式14)) –
「但它原來是
-1
」
您使用unsigned int
爲只看到32比0
更大的位值這麼做:
unsigned int a = 1;
a=(a<<31)>>31;
它是一個有符號的移位,所以最左邊的位將被擴展。這樣整體數字就在0的同一側。
通過左移這麼多,您將最低位放入符號位並以負數結束。
當你做一個右移,它的符號擴展,將符號位複製到低31位。
如果你想知道最低位只是做& 1
。
看看它在步驟:
#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
,您將獲得您期望的行爲。
查找符號擴展名。然後再用一個unsigned int再試一次。 – ClickRick
if'unsigned int a = 1'then everything everything right –
答案指的是運算符'>>>',它絕對不是C++運算符,所以我不認爲它是重複的。 –