《 C 語言的一些“騷操作”及其深層理解》之關(guān)于補(bǔ)碼與關(guān)于-1
關(guān)于補(bǔ)碼
補(bǔ)碼是一個(gè)很基礎(chǔ)的概念,但是對于很多人來說,其實(shí)有些迷糊,這里對補(bǔ)碼進(jìn)行一些通俗而深刻的講解。
C語言中的整型類型有兩種,無符號與有符號。無符號比較好理解,如圖2.8所示。
圖2.8 無符號整型的數(shù)值表達(dá)
只需要將每一個(gè)位乘以它的權(quán)值,再求和即是其所表達(dá)的數(shù)值。它所有的位都用來表達(dá)數(shù)值,因此上圖中類型能表達(dá)的范圍為0~255(8個(gè)位)。但是如何表達(dá)負(fù)數(shù),比如-10,這個(gè)時(shí)候就涉及到補(bǔ)碼了,如圖2.9所示。
圖2.9 有符號整型的數(shù)值表達(dá)
有符號整型的最高位被定義為符號位,0為正數(shù),1為負(fù)數(shù)。上圖中前一行等于+76,后一行等于多少?-76?那就錯(cuò)了。對于負(fù)數(shù)的數(shù)值要按其補(bǔ)碼來計(jì)算,如圖2.10所示。
圖2.10 有符號整型負(fù)數(shù)數(shù)值計(jì)算方法
為什么要引入補(bǔ)碼的概念,符號位表示符號,其它位直接表示其絕對值,不是更好嗎?這其實(shí)是一個(gè)數(shù)字游戲。我們要知道一個(gè)前提:CPU中只有加法器,而沒有減法器。OK,我們看下面的例子。
圖2.11 使用補(bǔ)碼通過加法實(shí)現(xiàn)減法操作
可以看到,補(bǔ)碼將符號位也統(tǒng)一到了計(jì)算過程中,并且巧妙的使用加法實(shí)現(xiàn)了減法操作。這對于簡化CPU中的算術(shù)邏輯電路(ALU)具有重要意義。
關(guān)于-1
為了說明關(guān)于-1的問題,我們先來看一個(gè)例子:
signed short a=-1;
if(-1==a)
{
//....
}
這個(gè)if條件成立嗎?似乎這是一句廢話。其實(shí)不然,它不一定成立。
我們要知道C語言中的判等==運(yùn)算是一種強(qiáng)匹配,也就是比較的雙方必須每一個(gè)位都匹配才被認(rèn)為相等。上例中,a在內(nèi)存中的表示是0XFFFF(補(bǔ)碼),但是-1這個(gè)常量在內(nèi)存中的表示在不同的硬件平臺(tái)上卻不盡相同,在16位CPU平臺(tái)上是0XFFFF,它們是相等的。而在32位CPU平臺(tái)上則是0XFFFFFFFF,它們就不相等。所以穩(wěn)妥的辦法是:
signed short a=-1;
if(((signed short)-1)==a)
{
//....
}
我們看到-1的補(bǔ)碼是全F,而且位數(shù)與CPU平臺(tái)相關(guān)。所以-1經(jīng)常還有另一個(gè)妙用,即可以用于判斷硬件平臺(tái)的CPU位數(shù),便于提高代碼的可移植性(32位平臺(tái)的int(-1)為0XFFFFFFFF,而16位平臺(tái)則是0XFFFF)。