關於0x80000000為什麼等於-2147483648和負數在記憶體上儲存的問題
1·先說明負數怎麼儲存
(1)十進位制負數是以其補碼儲存在記憶體上。 驗證:求-8在記憶體上以二進位制形式1的個數 思路是:拿變數,令值為1,與-8的二進位制碼的每一位做與運算,若與運算結果為1,則該位為1。
int NumberOf1(int n) { int count = 0; unsigned int value = 1; while (value != 0) { if (value&n) { count++; } value = value << 1; //左移右邊補0,當移完32為value為0. } return count; }
結論: 輸入-8,結果為29。
在32位系統上,
-8的儲存
-8的儲存是以-8的補碼,儲存在記憶體上。
-8的原碼 1000 0000 0000 0000 0000 0000 0000 1000
取反 由於第一位是符號位 不用改變 得:1111 1111 1111 1111 1111 1111 1111 0111
補碼=反碼+1 得::1111 1111 1111 1111 1111 1111 1111 1000 得到1的數量正好為29,所以-8的補碼就是-8儲存在記憶體上的二進位制碼
(2)但是在十六進位制,負數在記憶體中儲存的是原碼
驗證:
對int test = 0x80000001 (對應十進位制為-1) 檢查其記憶體上的1的個數,發現只有2個1
故記憶體上原碼為 1000 0000 0000 0000 0000 0000 0000 0001.
對十六進位制的-8也是2個1
(3)我們來看看0x80000000的輸出
0x80000000 的二進位制位 原碼 1000 0000 0000 0000 0000 0000 0000 0000
若最高位為符號位,則為-0,可是輸出int i = 0x80000000 發現i= -(2^31)
原因是在十六進位制中負數的二進位制原碼的最高位是符號位,後面的31位為序號位,不是值位。1後面的000 0000 0000 0000 0000 0000 0000 0000,表示序號1,表示負數中,從小到大的第一位。 由於int的最小值為-2^31,排在負數從小到大的序號1,所以int i = 0x80000000 輸出為 -(2^31)
我們來看看0xFFFFFFFF 原碼 1111 1111 1111 1111 1111 1111 1111 1111 最高位為1 ,為負數,序號位為第(2^31)-1位 (111 1111 1111 1111 1111 1111 1111 1111=(2^31-1) 所以0xFFFFFFFF為負數從小到大 第2^31-1位 ,即 -2^31+2^31-1= -1 輸出int i = 0xFFFFFFFF 為 -1 符合
(4)十進位制的補碼也符合 符號位+序號位的原則 就拿-8來做例子: -8的補碼:1111 1111 1111 1111 1111 1111 1111 1000 可以看出最高位為1 序號位為第2^(31)-8位,(111 1111 1111 1111 1111 1111 1111 1000 = 2^(31)-8 ) 則該補碼錶示的值為2^31- 2^(31)-8 = -8 符合
相關知識點補充: 十六進位制用最高位作為符號位,1位負數,0為正數。 負數的位右移運算: 原則:若右移的數字為負值,則向右移動N位同時N個1補充在左邊 若為正值,則以N個0補充在左邊