1. 程式人生 > >關於0x80000000為什麼等於-2147483648和負數在記憶體上儲存的問題

關於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補充在左邊