從原始檔到可以行檔案的過程
:預處理——編譯——彙編——鏈結
第一步預編譯:
$gcc -e hello.c -o hello.i
或者$cpp hello.c > hello.i
注:『-e』選項表示只進行預編譯;cpp是預編譯器
預編譯主要處理一『#』開頭的預編譯指令:
將所有的"#define"刪除,並且展開所有的巨集定義
處理所有條件預編譯指令
處理"#include",將包含的檔案插入到該預編譯指令的位置。注意,這個過程是遞迴進行
刪除所有注釋
新增行號和檔名標識,以便於除錯和編譯產生的錯誤和警告
保留所有"#pragma"指令,編譯器需要使用它們
編譯:
$gcc -s hello.i -o hello.s
也可以將編譯和預編譯合併,通過乙個gcc提供的程式ccl來完成:
$/usr/lib/gcc/usr/lib/gcc/i686-pc-cygwin/ccl hello.c
或者:$gcc -s hello.c -o hello.s
實際上gcc這個命令只是一些列後台程式的包裝,它會根據不同的引數要求去呼叫預編譯程式ccl、彙編器as、聯結器ld。
彙編:是將彙編**轉換為機器碼的過程
這樣來完成彙編:
$as hello.s -o hello.o
或者:$gcc -c hello.s -o hello.o
或者:從.c檔案開始
$gcc -c hello.c -o hello.o
需要經過下面的一些命令來完成:
ld -static crt1.o crti.o crtbegint.o hello.o -start-group -lgcc -lgcc_eh
-lc-end-group crtend.o crtn.o
注:到後面的時候記錄一下各個引數的作用,然後在這裡補充
編譯器都做了什麼:
編譯過程一般可以分為6步:掃瞄、語法分析、語義分析、源**優化、**生成和目標**優化。
詞法分析:
運用有限狀態機(finite state machine)可以輕鬆的將源**的字串行分割成一系列的記號。
此法分析產生的記號一般有一下幾類:關鍵字、識別符號、字面量(包含數字、字串等)和特殊符號(如加號、等號)
語法分析:
語法分析器(grammar parser)將對由掃瞄器產生的記號進行語法分析,從而產生語法樹。
由語法分析器生成的語法樹就是以表示式為節點的樹。
語義分析:
編譯器所能分析的語義是靜態語義,所謂靜態語義是指在編譯期間可以確定的語義,與之相對應的動態語義,就是在執行期才能確定的語義。
函式訪問必須知道目標函式的位址,變數訪問也必須知道目標變數的位址,所以這兩種方式都可以歸結為一種方式,那就是模組間符號的引用。
人們把每個源**模組獨立地編譯,然後按照需要將它們組裝起來,這個組裝模組的過程就是「鏈結」
鏈結的主要內容就是把各個模組之間相互引用的部分處理好,使得各個模組之間能夠正確銜接。
重定位發生在鏈結階段,如果乙個模組需要使用另乙個模組的變數或函式,編譯的時候先給這個變數或函式乙個特殊的位址,鏈結的時候再來確定實際位址。這個 位址修正的過程也叫做重定位,每個要被修正地方叫乙個重定位入口。
《程式設計師的自我修養》第二章學習筆記
第二章 編譯和鏈結 2.1被隱藏了的過程 我們知道,乙個程式由源 到可執行檔案往往由這幾步構成 預處理 prepressing 編譯 compilation 彙編 assembly 鏈結 linking 如圖所示,2.1.1預編譯 includeint main void 如上述檔案hello.c,...
《程式設計師的自我修養》筆記
以下是我讀此書時作的一些筆記,當然書中還有很多值得參考的想法,就不一一枚舉了。一萬小時說法 這個說法很普遍了,它再次提醒了我如何去做乙個領域的專家。如果平均每天八小時在這個領域上,那麼一年300天 300 8 2400,保持這種學習激情在上面,五年內就可以成為專家了,我算了算自己在這個領域投入的時間...
程式設計師的自我修養
一忌 輕易言敗,沒有自信 沒有永不放棄精神的程式設計師,只是乙個有程式設計師名號的假程式設計師。乙個真正的程式設計師,知道在程式設計的過程中,可能會遇到不計其數的困難和問題,可能有極多的挫折和失敗,而成功只有一次。就為解決乙個問題,我們可能連續十幾甚至幾十小時的坐在計算機前不停的工作。乙個問題解決了...