1. 程式人生 > >C++ 原碼、補碼和反碼解析

C++ 原碼、補碼和反碼解析

首先對於有符號數,第一位的位置是表示的正負,為1時是負數,為0時是正數

其次,正數的原碼、補碼、反碼一致

負數的反碼是原碼的數值位(也就是除了第一位的符號位之外)取反,負數的補碼是反碼加1 

在計算機中帶符號的整數都是採用二進位制的補碼進行儲存,資料在記憶體中始終是以二進位制形式存放的,數值是以補碼錶示的。

無論32位還是64位,int都是4個位元組,32位,表示的範圍為-2147483648~2147483647,32為最小負整數的補碼錶示為:1000 0000 0000 0000 0000 0000 0000 0000

~i 對每一位取反運算

-i 取反加1

1-i 補碼+1的補碼

-1-i -1的補碼加上-i的補碼

計算機中的有符號數和無符號數的機器碼(補碼)是一樣的,同一個二進位制碼按照有無符號輸出結果不一樣。

//關於資料在計算機記憶體中的儲存:無論什麼數值,也無論這個數值是用什麼進製表示,計算機儲存的都是這個數值的補碼。

//如果表示這個數值的時候,前面有+號或者沒有加符號,則認為是正數,這個時候就是把這個數值轉換為二進位制後直接存入計算機,因為正數的補碼就是其本身(注意:儲存的時候只會看有沒有加+號來標識,而不看其實際意義,如(int)x80000001前面沒有加符號,則預設其是一個正數,儘管它最高位是並且如果看成正數則實際上已經越界,在存入計算機的時候也會當做正數來計算補碼然後存入計算機,這一點可以通過檢視memory來證實,記憶體中也是儲存的x80000001);

//如果表示這個數值的時候,前面加了-號來標識這是一個負數,則需要先轉換成二進位制再按照計算負數補碼的步驟變換成補碼再存入計算機記憶體,(注意:儲存的時候只會看有沒有加-號來標識,也不看起實際意義,如(int)-0x80000001是一個負數,儘管這個數值已經沒有實際意義,因為如果將後面看做一個正數實際上已經越界,整體上如果看成負數也已經越界,但是計算機會計算它的補碼,然後存入記憶體這一點可以通過檢視memory來證實,記憶體中儲存的是x7fffffff

//關於補碼的計算規則:以前一直是將原碼除符號位逐位取反,然後末位加得到補碼,但是這樣-0x80000001得到的補碼應該是xffffffff,但是實際檢視得到的是x7fffffff。所以應該是,將-號後面的數只管展開成正數的二進位制形式,如果不夠所需的型別的長度前面補零,如果超過了將超出的位數捨棄,然後除了所需型別的最高符號位之後的都逐位取反末位加,最後將符號位加,溢位的位捨去,這樣-0x80000001的補碼計算之後得到的就是x7fffffff。這個補碼的計算方法可以通過計算short型別的-0x18001來得到確認(開始的時候推測是將-0x80000001擴充套件成了long之後求補碼截斷所得,但是通過求sizeof(0x80000001)得到的是否定了這種假設)。

//關於數值型別擴充套件:當需要把一個短型別轉換成一個長型別的時候,需要先將數值轉為補碼形式,然後通過位擴充套件來進行,在位擴充套件的時候,只看需要擴充套件的數值的符號位,如果是則將符號位之前填充即可,如果是1則填充1需要將一個長型別轉換成一個短型別的時候,先將這個數值表示為補碼形式,然後從後向前擷取需要的位數即可。。