1. C程序編譯
C程序的編譯可以簡(jiǎn)單分為4個(gè)步驟:預(yù)處理摊唇,編譯,匯編涯鲁,巷查。
- 預(yù)處理 展開(kāi)頭文件·刪除注釋,條件編譯(例如#if抹腿,#ifdef)岛请,宏定義展開(kāi) (.i文件) gcc -E ex.c -o ex.i
- 編譯 檢查語(yǔ)法,將高級(jí)語(yǔ)言轉(zhuǎn)換成匯編語(yǔ)言(.s文件) gcc -S ex.i -o ex.s
- 匯編 將匯編語(yǔ)言轉(zhuǎn)化為機(jī)器語(yǔ)言(.o文件) gcc -c ex.s -o ex.o
- 鏈接 鏈接不同系統(tǒng)下的庫(kù)文件(可執(zhí)行文件) gcc ex.o ex
2. 原碼警绩、反碼髓需、補(bǔ)碼
2.1 基礎(chǔ)概念
- 數(shù)據(jù)在技術(shù)及內(nèi)部是以補(bǔ)碼的形式存儲(chǔ)的
- 數(shù)據(jù)分為有符號(hào)數(shù)和無(wú)符號(hào)數(shù)。
- 正數(shù)的首位地址為0房蝉,其原碼是有十進(jìn)制轉(zhuǎn)二進(jìn)制
- 負(fù)數(shù)的首位地址為1僚匆,其原碼是十進(jìn)制數(shù)轉(zhuǎn)二進(jìn)制數(shù),再講首位地址改為1搭幻。
- 對(duì)于一個(gè)數(shù)字咧擂,技術(shù)及要使用一定的編碼方式進(jìn)行存儲(chǔ),原碼檀蹋、反碼松申、補(bǔ)碼是機(jī)器存儲(chǔ)一個(gè)具體數(shù)字編碼方式。
2.2 具體方式
原碼
符號(hào)位(首位)加上真值得絕對(duì)值俯逾。
int 12的原碼--->0000 0000 0000 0000 0000 0000 0000 1100(補(bǔ)全所有位)
int -12的原碼--->1000 0000 0000 0000 0000 0000 0000 1100
反碼
正數(shù)的反碼與原碼相同贸桶,負(fù)數(shù)的反碼是除符號(hào)位,其余位取反桌肴。
int 12的反碼--->0000 0000 0000 0000 0000 0000 0000 1100(補(bǔ)全所有位)
int -12的反碼--->1111 1111 1111 1111 1111 1111 1111 0011
補(bǔ)碼
正數(shù)的補(bǔ)碼與原碼相同皇筛,負(fù)數(shù)的補(bǔ)碼是反碼基礎(chǔ)上加1
int 12的反碼--->0000 0000 0000 0000 0000 0000 0000 1100(補(bǔ)全所有位)
int -12的反碼--->1111 1111 1111 1111 1111 1111 1111 0100
2.3 三種編碼方式各自的用處
<font size=4 color=red> 計(jì)算機(jī)只做加法運(yùn)算。</font>
- 情景1:兩個(gè)正數(shù)進(jìn)行運(yùn)算坠七,原碼即可解決
10+2
1010 +
0010
_______________
1100----->(12)
- 情景2:一正一負(fù)水醋,10+(-2),
//原碼
10+(-2)
1010 +
1010
_______________
10100----->(20)
//結(jié)果明顯是不對(duì)的,那就說(shuō)明負(fù)數(shù)與正數(shù)之間采用的不是原碼
//反碼
10+(-2)
0000 0000 0000 0000 0000 0000 0000 1010 +
1111 1111 1111 1111 1111 1111 1111 1110
_________________________________________
1 0000 0000 0000 0000 0000 0000 0000 1000
//我們發(fā)現(xiàn)彪置,好像除去符號(hào)位的話拄踪,結(jié)果是正確的。但是有一種情況還例外
10+(-10)
0000 0000 0000 0000 0000 0000 0000 1010 +
1111 1111 1111 1111 1111 1111 1111 0101
_________________________________________
1111 1111 1111 1111 1111 1111 1111 1111--->1000 0000 0000 0000 0000 0000 0000 (原碼)
//除去符號(hào)位拳魁,好像結(jié)果出乎意料了啊惶桐,是-0。
//再試一下
1+(-1)
0001
1110 +
__________
1111 ----->1000(原碼)
//還是-0
//雖然人們理解上+0和-0是一樣的, 但是0帶符號(hào)是沒(méi)有任何意義的. 而且會(huì)有[0000 0000]原和[1000 0000]原兩個(gè)編碼表示0.
//于是補(bǔ)碼的出現(xiàn), 解決了0的符號(hào)以及兩個(gè)編碼的問(wèn)題:
1+(-1)
0000 0000 0000 0000 0000 0000 0000 0001
1111 1111 1111 1111 1111 1111 1111 1111 +
____________________________________________
1 0000 0000 0000 0000 0000 0000 0000 0000--->原碼(0000 0000 0000 0000 0000 0000 0000 0000)
//補(bǔ)碼
10+(-2)
0000 0000 0000 0000 0000 0000 0000 1010 +
1111 1111 1111 1111 1111 1111 1111 1110
_________________________________________
1 0000 0000 0000 0000 0000 0000 0000 1000
//首位的1,數(shù)據(jù)溢出了姚糊,系統(tǒng)自動(dòng)將其舍棄了想虎。所以結(jié)果是 1000(補(bǔ)碼)
//1000(補(bǔ)碼) 首位是1,說(shuō)明它是正數(shù)叛拷,正數(shù)的原碼,補(bǔ)碼相同岂却,其結(jié)果轉(zhuǎn)化為十進(jìn)制8忿薇。
總結(jié):根據(jù)以上的代碼,可以確定的話0的話只有+0躏哩,沒(méi)有-0署浩,所謂的0不帶符號(hào),其實(shí)就是把它包含進(jìn)了正數(shù)范圍去了扫尺。
這樣的話筋栋,假設(shè)我們現(xiàn)在的int是4Byte的,那么(10000 0000 0000 0000 0000 0000 0000 0000)其實(shí)是沒(méi)有反碼和原碼的正驻,因?yàn)槟愕谝晃槐硎痉?hào)弊攘,你根本無(wú)法減1,去轉(zhuǎn)換反碼姑曙。
-1-int的最大值(2^31-1)的補(bǔ)碼結(jié)果就是(10000 0000 0000 0000 0000 0000 0000 0000)襟交,因?yàn)閷?shí)際上是使用以前的-0的補(bǔ)碼來(lái)表示,所以沒(méi)有反碼和原碼的伤靠。
(10000 0000 0000 0000 0000 0000 0000 0000)其實(shí)就是(-2^31)捣域, 所以int的最小范圍就是這個(gè),而不是((-2^31)+1)宴合。
使用補(bǔ)碼焕梅,不僅解決了0的問(wèn)題,還能多表示一個(gè)最低數(shù)卦洽。
參考: