上一章(1.1-1.4)LZ和各位簡單的探討了一下計算機(jī)系統(tǒng)中的一些基本概念,本次我們將進(jìn)入一個嶄新的世界,。在1.1那一章當(dāng)中,,我們已經(jīng)簡單的提及了信息的概念,本次我們會逐漸深入的討論信息的相關(guān)內(nèi)容,。
引言
我們很難想象,,1和0這兩個再簡單不過的數(shù)字,,給計算機(jī)科學(xué)帶來了徹底的改變。對于無法與人腦相比的計算機(jī)來說,,簡單的1和0就是最適合它們的數(shù)字,。不過1個1或者1個0往往代表不了任何意義,它們必須被賦予上下文,,才能有具體的含義,。比如,如果我們知道1和0是代表的布爾類型的值,,那么我們就知道1是true,,0是false。
對于二進(jìn)制所表示的數(shù)字來說,,主要有三種,,即無符號、補(bǔ)碼以及浮點(diǎn)數(shù),。
由于計算機(jī)對于固定類型的二進(jìn)制數(shù)字往往都是有位數(shù)限制的,,比如int類型使用四個字節(jié)(32位二進(jìn)制)來表示,因此在計算的時候,,會發(fā)生溢出的情況,,最簡單的我們使用無符號整數(shù)0xFFFFFFFF與無符號整數(shù)0xFFFFFFFF相乘,則會產(chǎn)生溢出,。
在產(chǎn)生溢出的時候,,得出的結(jié)果往往會令人大跌眼鏡。比如兩個正數(shù)相乘可能得到負(fù)值,,兩個正數(shù)相加也可能得到負(fù)值,。而對于不同的計算機(jī)來說,由于數(shù)值范圍可能有所不同,,因此掌握信息相關(guān)的內(nèi)容對于寫出跨平臺的程序來講也是很有幫助的,。
信息的存儲
大多數(shù)計算機(jī)使用8位的塊,或者說字節(jié),,來作為最小的可尋址的存儲器單位,,而不是在存儲器中訪問單獨(dú)的位。換句話說,,我們在訪問存儲器的內(nèi)容時,,最小的訪問單位一般是字節(jié)。
在我們編程的時候,,往往會把虛擬存儲器(virtual memory)抽象為一個字節(jié)數(shù)組,,而每一個數(shù)組內(nèi)的元素或者說字節(jié)都有唯一的地址(address),這些地址的集合就被稱作虛擬地址空間,。虛擬地址空間是為了給機(jī)器級的程序一個概念上的映像,實(shí)際上為了提供這個映像,內(nèi)部的實(shí)現(xiàn)是非常復(fù)雜的,。
十六進(jìn)制表示法
對于機(jī)器來說,,可能比較喜歡0和1,但是對于人類這種高級生物來說,,1和0就有點(diǎn)不夠看了,。因此通常情況下,為了便于閱讀,,我們會使用十六進(jìn)制去表示二進(jìn)制,。1位十六進(jìn)制的數(shù)字可以表示4位二進(jìn)制數(shù)字,因此一個字節(jié)就可以表示為0x00---0xFF,。
有關(guān)十六進(jìn)制,、二進(jìn)制以及十進(jìn)制的轉(zhuǎn)換,LZ這里就直接略過了,,相信大部分人應(yīng)該都對這個轉(zhuǎn)換并不陌生,。
字
每臺計算機(jī)都有一個字長(word size),用于指明整數(shù)和指針數(shù)據(jù)的標(biāo)準(zhǔn)大?。╪ominal size),。而由于虛擬地址空間中的地址就是使用一個字來表示的,因此操作系統(tǒng)中的字長就決定了虛擬地址空間的大小,。
比如32位操作系統(tǒng)下,,最大內(nèi)存就是232 = 4 * 210 * 210 * 210 B = 4GB,而在64位操作系統(tǒng)下,,LZ還專門問了問群里的猿友,,最終得到的結(jié)果是234GB。
數(shù)據(jù)大小
由于計算機(jī)位數(shù)的不同,,會造成在數(shù)據(jù)類型的存儲上,,采用的位數(shù)略有不同,下表是在32位和64位機(jī)器下,,C語言當(dāng)中的數(shù)字?jǐn)?shù)據(jù)類型需要的位數(shù),。
可以看出,對于長整形以及字符指針類型來說,,在32位和64位系統(tǒng)下的字節(jié)數(shù)是不同的,。特別的,對于指針類型來說,,所有指針類型在32位下都是4位,,而在64位下都是8位,這是由虛擬地址空間的地址位數(shù)或者說字長所決定的,。
尋址和字節(jié)順序
對于跨越多個字節(jié)的程序?qū)ο螅ǔ绦驅(qū)ο笾钢噶?、?shù)據(jù)或者控制信息等,,是程序當(dāng)中對象的統(tǒng)稱)來說,我們需要制定兩個規(guī)則,,才能唯一確定一個程序?qū)ο蟮闹怠?/p>
比如對于int類型的值0xFF來說,,如果我們要根據(jù)虛擬內(nèi)存地址去獲取這個整數(shù)值,那么首先我們需要知道它的起始虛擬內(nèi)存地址是多少,。另外,,我們還需要知道,對于表示int類型的四個字節(jié)來說,,這四個字節(jié)的排列順序,。
對于第一個問題,由于大部分計算機(jī)都采用連續(xù)的內(nèi)存地址去存儲一個程序?qū)ο?,因此我們稱內(nèi)存地址中最小的那個就是該程序?qū)ο蟮钠鹗嫉刂?,也是該程序?qū)ο蟮牡刂贰?/p>
對于第二個問題,一般有兩種方式,,即大端法和小端法,。對于一個整數(shù)0x000000FF來說,我們假設(shè)它的起始地址為0x1,,那么對于使用大端法規(guī)則的系統(tǒng)來說,,0x1-0x4的虛擬內(nèi)存所存儲的值依次為0x00、0x00,、0x00,、0xFF,相反對于采用小端法規(guī)則的系統(tǒng)來說,,0x1-0x4的虛擬內(nèi)存所存儲的值依次為0xFF,、0x00、0x00,、0x00,。
強(qiáng)制類型轉(zhuǎn)換
對于一個特定的數(shù)據(jù)類型來講,計算機(jī)在解釋這類數(shù)據(jù)的值的時候,,是根據(jù)起始位置以及數(shù)據(jù)類型的位數(shù)來確定的,。比如對于無符號int類型的數(shù)據(jù)來說,倘若我們知道它的起始位置為0x1,,而當(dāng)前的操作系統(tǒng)采取的是大端法規(guī)則,,假設(shè)0x1-0x4的內(nèi)存地址中存儲的字節(jié)依次為0xFF,0xFF,,0xFF,,0xFF,由此計算機(jī)將會幫我們計算出這個無符號int類型的值為232-1,,也就是無符號int類型的最大值,。
這其中計算機(jī)是根據(jù)0x1-0x4這四個字節(jié)上的值,,以及無符號int類型的解釋方式,最終得到的這個無符號int類型的值,。
由此可見,,計算機(jī)在解釋一個數(shù)據(jù)類型的值時主要有四個因素:位排列規(guī)則(大端或者小端)、起始位置,、數(shù)據(jù)類型的字節(jié)數(shù)、數(shù)據(jù)類型的解釋方式,。
對于特定的系統(tǒng)來說,,前兩種因素都是特定的,而對于后兩種因素的改變,,則可以改變一個數(shù)據(jù)類型的值的最終計算結(jié)果,,這就是強(qiáng)制類型轉(zhuǎn)換。對于大部分高級程序設(shè)計語言來講,,都提供了強(qiáng)制類型轉(zhuǎn)換,。
比如C語言,我們可以將一個無符號int類型的值強(qiáng)制轉(zhuǎn)換為其它類型,,在轉(zhuǎn)換之后,,對于上面四個因素之中,改變的是最后兩個,。為此我們寫一個小程序來看下這個有意思的事情,。
#include <stdio.h>
int main(){
unsigned int x = 0xFFFFFF61;
int *p = &x;
char *cp = (char *)p;
printf("%c\n",*cp);
}
這是一個簡單的強(qiáng)制類型轉(zhuǎn)換示例,可以看到我們將一個無符號int類型的值,,先賦給了一個int類型的指針,,又強(qiáng)制轉(zhuǎn)換成了char類型的指針,最終我們輸出這個char類型指針?biāo)淼淖址?,結(jié)果的輸出是一個a,。
輸出a的原因就是由上面的四個因素決定的,我們看這個具體程序上的四個因素,。
1,、cp指針的值與x變量的起始內(nèi)存地址相等。(起始位置)
2,、LZ的linux系統(tǒng)是小端表示法,,也就是說假設(shè)x變量的起始內(nèi)存地址為0x1,那么0x1-0x4的值分別為0x61,、0xFF,、0xFF、0xFF,。(位排列規(guī)則)
3,、char只占一個字節(jié),,因此會只讀取0x61這個值。(數(shù)據(jù)類型的字節(jié)數(shù),,或者說大?。?/p>
4、0x61為十進(jìn)制的97,,對應(yīng)ascii表的話,,代表的是字符a,因此最終輸出了a,。(數(shù)據(jù)類型的解釋方式)
可以看出,,強(qiáng)制類型轉(zhuǎn)換有時候會讓結(jié)果變的讓人難以預(yù)料,因此這種技巧一般不太推薦使用,,但是這種手段也確實(shí)是程序設(shè)計語言所必需的,。
字符串的表示
這一點(diǎn)其實(shí)上面我們已經(jīng)提到了,我們知道97其實(shí)代表的是字符'a',,而這個的由來就是根據(jù)ascii表來的,,我們在linux系統(tǒng)上可以輸入man ascii命令來查看。
代碼的表示
二進(jìn)制如何表示代碼,?
其實(shí)這些都是編譯器的責(zé)任了,,我們只需要寫出像上面那個小程序一樣的人們可以看懂的代碼,編譯器便會幫我們將其翻譯成對應(yīng)的機(jī)器所認(rèn)識的二進(jìn)制序列,。從這個角度上來講,,程序語言其實(shí)就是一個二進(jìn)制序列的簡單描述,它提供我們更簡單的編寫計算機(jī)可以執(zhí)行的二進(jìn)制序列的方式,。
文章小結(jié)
本次我們初步探索了信息的存儲以及信息所代表的結(jié)果的計算,,這些內(nèi)容都比較基礎(chǔ),相信不難看懂,。