來自:碼農翻身(微訊號:coderising)
我從無邊無盡的黑暗中慢慢醒來,迷迷糊糊,茫然四顧。
耳邊傳來了風扇賣力幹活的嗡嗡聲,估計就是他把我吵醒的。 這時候 CPU阿甘 現身了:“兄弟,快醒醒,開機了,要幹活了,我要把程式和資料從硬碟讀取到你這裡來了!”
“放到我這裡幹嘛?”
“唉,一斷電,你什麼都忘了,不把程式讀入記憶體,我怎麼執行啊?”
奧,對了,我是記憶體啊,阿甘是我的好基友,雖然說程式都在硬碟上存著,但是阿甘被設計成只能執行我記憶體中的程式,所以程式必須要裝載進來。
在這個系統裡,阿甘最快,我第二, 硬碟則慢如蝸牛,他整天叫囂著說要提高訪問速度,到時候可以把我徹底替換掉, 但是這麼多年過去了,還是沒有什麼進展。
不知道等了多長時間,阿甘終於把一個叫做Linux的作業系統給裝載到我這裡來了,阿甘說從此以後它就是這裡的老大。
可是我卻感覺不到老大的存在,我只知道我那一個個電容所代表的0和1 ,由於這些電容不能持久地保持電荷,我得定期地去掃清,如果不及時掃清,那些0和1的資料就會丟失,這將是極為嚴重的事故,主人就會把我從主機板上拔掉,用另外一個傢伙來替換我,決不允許這樣的事情發生!
次序問題
但是程式員們卻不管什麼電容,什麼掃清,在他們的眼裡,我就是一個個的空格子,每個格子有個唯一的地址,就像門牌號一樣。
我最小的一個格子就是一個bit ,只能儲存0和1,這實在是太小了, 人們把8個bit 稱為一個位元組(Byte), 就可以表達2的8次方種可能,從00000000 到 11111111, 如果是無符號數的話,就是0~255。
很明顯,Byte還是太小,人們又把更多的位元組(比如4個)組織起來,叫做一個Word(字) 。
位元組數目一多,就出現了很有意思的問題,比如說有個整數,十六進位制的值是0x1234567, 一共是四個位元組,那該以什麼次序儲存他們呢?
一種辦法是這樣:
還有一種方法是這樣:
可笑的是人類為這兩種方式爭執不休,有人堅決支援第一種(即大端法),有人則捍衛第二種(即小端法),還有些和稀泥的傢伙,大端小端都支援,就看你怎麼選擇和配置了。
我問CPU阿甘:“如果兩個機器的位元組次序不同,他們兩個通訊的時候,豈不天下大亂?”
阿甘嘆息一聲:“唉,他們在制定TCP/IP的時候,確定了統一的網路次序,使用大端法來傳輸資料。作業系統老大會提供特定的函式來實現網路和主機之間位元組次序的轉換,比如 htonl 函式,就可以把32位整數由主機位元組次序轉換為網路位元組次序, ntohl則恰恰相反。 ”
編譯器
剛才說到,記憶體中每個位元組都有一個唯一的地址,只要能記住這個地址就可以把這個位元組的值給取走,或者寫入一個值。
比如說,剛才CPU阿甘執行了一些列的指令, 它把地址0x100處的值取出來,和 0x104處的值相加,放到0x110處, 然後再和0x108處的值相乘,結果放到0x10C處。
這一系列操作搞得我眼花繚亂,我對CPU阿甘說:“這程式員真是很厲害,居然能夠記住這麼多地址!”
阿甘說:“怎麼可能? 他們笨得很,根本記不住,全靠了編譯器的幫忙。”
“編譯器? ”
“是啊,編譯器允許程式員用變數的方式來表達程式,它可以把這些變數轉換成地址。沒有編譯器,程式員將會像熊貓一樣稀少。”
total = base + bonus
tax = total * rate
原來如此,我這裡看到的都是二進位制的值,沒想到程式員都給他們起了一個名字。
資訊 = 位 + 背景關係
有一次, 阿甘問我地址0x300的值是多少,我看了一眼,告訴他說是一個32位整數1735159650。
阿甘大驚失色:“兄弟,你睡了一覺什麼忘了嗎, 你不能擅自去解釋你記憶體資料的型別啊!”
“為什麼? 這就是個整數嘛!”
“你這裡的值實際上是0x 676C 6F62,他有可能是32位整數1735159650,也有可能是浮點數 1.116533*10^24,還有可能是機器指令呢!!記住!解釋權不在你,而在人家應用程式那裡,你就管好你電容裡的’二進位制’就行!”
我覺得很羞愧,這麼重要的準則都給忘記了!
資訊=位+背景關係, 我這裡只負責一串串的二進位制位,至於這些位的資訊是什麼,得加背景關係才能理解了。
指標
過了一會兒,阿甘問我0x108處存了什麼內容, 這一次我不再“解釋”了,我告訴他是0x100。
奇怪的是他接下來又問我0x100處的值是什麼, 我告訴他說是0x12C, 他這才滿意地離開。
我拉著他問道:“你這次怎麼了,這麼麻煩?還得讀兩次才行?”
他說:“沒辦法,程式員用指標了!”
int i = 300;
int *p = &i;
total = *p + 200;
“看到沒有,這個變數p就表示指標。”
我嚇了一跳:“難道我的格子裡儲存的不僅僅是值,而是地址?”
“是啊,這就再次證明,你不要胡亂解釋你儲存的值。 我告訴你,有時候還會出現二級指標呢。”
int i = 300;
int *p = &i; ;
int **pp = &p;
這真是顛覆了我的認知,我還是掃清我的電容去吧!
不過,在億萬次的讀寫操作中,我透過這些指標的關係,也發現了一些獨特的樣式,比如說我發現這樣的東西很常見:
我問阿甘:“這是在幹嘛? ”
“這就是程式員實現的連結串列啊。”
“ 那這個東西呢?”
阿甘說:“這不就是一顆二叉樹嘛! 程式員管這些東西叫做資料結構。”
我原來以為,我就是一個大陣列而已,沒想到透過指標,可以表達各種各樣的複雜的資料結構的,只要你能沿著指標來回跳轉就行。
但是我心裡隱隱覺得不妥,這指標實在是太強大了,程式員可以把它指向任何地方,我知道有些地方是作業系統老大的獨有區域,是嚴禁外界進入的,萬一指標指到這裡會發生什麼事?
阿甘說:“這不用你操心,如果有個程式透過指標想訪問它根本沒有許可權的區域,老大就會引發一個segment fault,把這個程式殺死!”
“殺死以後呢?”
“那個程式的記憶體空間就會被釋放, 與此同時老大會生成一個叫做core dump的檔案,讓程式員們去分析。 唉,今天你真是煩人,問了這麼多問題。 不說了,主人要關機了,明天再見!”
風扇停轉,電流消失,整個世界安靜了。
第二天
我從無邊無盡的黑暗中慢慢醒來,迷迷糊糊,茫然四顧。
耳邊傳來了風扇賣力幹活的嗡嗡聲,估計就是他把我吵醒的。 這時候CPU阿甘現身了:“兄弟,快醒醒,開機了,要幹活了,我要把程式和資料從硬碟讀取到你這裡來了!”
……
後記:本文的部分素材來源於《深入理解計算機系統》和《C和指標》, 這是兩本非常不錯的書,推薦給大家。
朋友會在“發現-看一看”看到你“在看”的內容