前天收到了K&R的中文版的書,期盼已久的書啊,心情有點小激動。
【練習1-1】
在“Hello world”程式中製造混亂。
這個我倒不是很想做,因為我自己不是個製造混亂的人,雖然有時在寫代碼的時候不能由自己控制,我倒是希望能在代碼中尋找 ladybug,嘻嘻。
這裡我們來看點別的:
1、ELF
我們在Linux下面編譯好後Hello world程式後,啟動並執行過程很簡單;但是我一直想探探,這裡到底發生了什麼。如果你對機器碼比較精通,那麼
od可以幫你解決這個問題,可問題是我不明白,因此我需要“曲線救國”。
我是這麼編譯的: gcc -Wall hello.c -o hello
很幸運,沒有錯誤,我能夠運行我的程式,但是我不想看自己啟動並執行結果,我這麼做了:
less hello, 結果Linux告訴我這個檔案可能是二進位檔案,問我是否依然開啟,這裡當然要開啟了,我不開啟找你Linux哥哥幹嘛。
輸出結果大家可以自己看看,我們先來看一行輸出:
看到什麼了,一堆的^A^A和^@, 我現在對這些不感興趣,感興趣的是前面的四個字元:
我們看到了:ELF,這個是啥意思呢?我們這裡看一段引自維基百科的內容容:
http://zh.wikipedia.org/wiki/%E5%8F%AF%E5%9F%B7%E8%A1%8C%E8%88%87%E5%8F%AF%E9%8F%88%E6%8E%A5%E6%A0%BC%E5%BC%8F
就是說,ELF表示這個檔案一個可以串連和可執行檔格式,也就是說這是一個binary格式的檔案,等會我們還可以單獨編譯一個函數試試。
至於ELF格式,在串連上有簡要的說明。
2、連結的庫
我們知道,在彙編器將.asm檔案翻譯成.o檔案後,還需ld將.o檔案連結成最終的可執行檔,這裡就需要用到先行編譯的庫檔案,那麼我們如何
查看檔案連結了那些庫檔案呢?別著急,雖然唐僧被老鼠精抓了,好歹他倆成不了親,聽我慢慢道來,我們可以看到下面這樣一段輸出:
咿呀,看到了沒,親們,這裡指出了我們連結時用到的庫檔案了,/lib/ld-linux.so.2, 大家可以搜尋一下,在你的電腦裡面(如果你安裝的時候
選擇了安裝開發工具的話)應該能找到這個檔案。
這個檔案是一個動態連接器檔案,在連結的時候需要用到,從 ld 這個首碼可以看出,他與連結器ld相關。其實這裡面還提示了很多其他的庫檔案。
3、GNU
整個輸出裡面還有三個字母比較醒目,那就是:GNU, 沒想到吧,在你編譯產生的目標檔案裡面居然還有GNU三個字母。
4、Hello world 字串
在整個檔案,還有一個比較醒目的地方:Hello world,這裡也能看到
這個地方就是我們將要輸出的字元
5、系統資訊,編譯器資訊,檔案節區資訊
這裡我們可以清楚的看到: .text、 .data 、 .bss、 .comment這些節區關鍵字的資訊,
我們可以看看我的GCC的版本資訊,是否和這裡提示的一樣。
很明顯,這裡提示的資訊與我們利用less查看的hello檔案一致。
6、readelf程式
其實Linux不但提供了二進位形式的二進位檔案查看工具od,還提供了一個更可視化的查看工具,readelf。我們可以看看readelf與less查看的內容有啥不一樣的
這裡可以看到,裡面的輸出內容與less命令輸出的有很多相似的地方,如果你對readelf比較熟悉的話,那麼結合less 命令,是不是能更好的理解呢?
7、 objdump
如果需要查看更加具體的內容,那麼我們還可以利用objdump工具,例如需要查看所有segment的內容,可以這樣: objdump -x hello
輸出結果如下:
可以看出,objdump提供的資訊比readelf工具更詳細。如果你對elf檔案的分析感興趣可以到這個連結看看:http://wenku.baidu.com/view/5ca21b28915f804d2b16c164.html
【練習1-2】
在printf函數使用 ‘\c’, 看看輸出結果是什麼,你說呢? 會輸出啥玩意
我們看到,printf輸出的時候,並沒有按照我們通常理解的那樣,字串字面值原樣輸出,這個很多人都是這麼認為的,實際? 這個在最初【C語言學習趣事】的時候,我曾經說過這個問題
我敢猜測,我們很多人在學習的時候,你的老師說過這樣話: printf函數的第一個參數的內容,如果不是用格式控制和逸出序列則原樣輸出。想想,你的老師是否這麼說過。
這是什麼原因呢? 嚕啦啦
【練習1-3】
【練習1-4】
【練習1-5】
這三個練習,需要注意的是整數的除法。