首先看代碼:
int main(){ int i=-2147483648; return printf("%d,%d,%d,%d",~i,-i,1-i,-1-i); }
輸出結果為:
2147483647,-2147483648,-2147483647,2147483647
這里就涉及到對負數取反,單目運算符“-”的理解,在int占4個字節,大小范圍為-2147483648~2147483648,最高位代表符號位,所以第32位為1,這里就需要理解計算機中負數的表示形式:
計算機中的數字都是以補碼的形式存放!
正數的原碼、反碼、補碼都相同
5在計算機中原碼、反碼、補碼均為:00000000 00000000 00000000 00000101
負數的反碼為對該數的原碼除符號位外各位取反,補碼為其反碼加1:
-5原碼為:10000000 00000000 00000000 00000101
反碼為:11111111 11111111 11111111 11111010
補碼為:11111111 11111111 11111111 11111011
所以-5在計算機中存儲形式為11111111 11111111 11111111 11111011轉換為十六進制為:0xFFFFFFFB
但是-2147483648比較特殊!
-2147483648原碼為:10000000 00000000 00000000 00000000 (表示-0)
反碼為:11111111 11111111 11111111 11111111
補碼為:00000000 00000000 00000000 00000000
+0的原碼、補碼、反碼均為00000000 00000000 00000000 00000000
如果用-2147483648用補碼00000000 00000000 00000000 00000000來表示則和0的補碼一樣,不能區分開;
所以計算機規定用10000000 00000000 00000000 00000000來表示-2147483648的補碼,
32位最小負整數的補碼為10000000 00000000 00000000 00000000
計算機中-2147483648取反為:01111111 11111111 11111111 11111111,此為存儲正數的補碼,換算原碼得到數為2147483647
單目運算符“-”為取負,-2147483648取負為2147483648,顯然超過int類型范圍(-2147483648~2147483647),剛好超過一個就變為-2147483648,所以其對應的補碼仍為10000000 00000000 00000000 00000000,
對應補碼理解就是-x=~x+1;即補碼取反加1,10000000 00000000 00000000 00000000取反加1后任然為10000000 00000000 00000000 00000000,對應數為-2147483648
1-i為(-i)+1,對應補碼為:
10000000 00000000 00000000 00000000+00000000 00000000 00000000 00000001=10000000 00000000 00000000 00000001
轉換為十進制為:- 2147483647
-1-i為(-i)+(-1),對應補碼為:
10000000 00000000 00000000 00000000+11111111 11111111 11111111 11111111=01111111 11111111 11111111 11111111
轉換為十進制為: 2147483647
其實也可以從十進制理解:-2147483648-1=-2147483649,超過范圍后變為2147483647