天天看點

C語言編譯與連結

程式由源檔案到可執行檔案,一般經過預處理(Prepressing)、編譯(Compilation)、彙編(Assembly)和連結(Linking)這四個階段。如下圖表示

C語言編譯與連結

預處理

預處理過程主要處理那些源代碼檔案隻能夠的以”#”開始的預編譯指令。比如“#include”、“#define”等,主要處理規則如下:

(1)将所有的“#define“删除,并且展開所有的宏定義;

(2)處理所有條件預編譯指令,比如”#if“、”#ifdef“、”#elif“、”#else“、#endif;

(3)處理”#include“預編譯指令,将被包含的檔案插入到該預編譯指令的位置。注意:這個過程是遞歸進行的,也就是說被包含的檔案可能還包含其他檔案;

(4)删除所有的注釋”//“和”、”“;

(5)添加行号和檔案名辨別,比如#2 “test.c” 2,以便于編譯時編譯器産生調試用的行号資訊及用于編譯時産生編譯錯誤或警告時能夠顯示行号;

(6)保留所有的#pragma編譯器指令,因為編譯器需要使用它們;

編譯

編譯過程就是把預處理完的檔案進行一系列的詞法分析、文法分析、語義分析以及優化,在确認所有的指令都符合文法規則之後,将其翻譯成等價的中間代碼表示或彙編代碼,這個過程往往是我們所說的整個程式的建構的核心部分,也是最複雜的部分之一。

彙編

彙編實際上指彙編器(as)把彙編語言代碼翻譯成目标機器指令的過程。目标檔案中所存放的也就是與源程式等效的目标的機器語言代碼。目标檔案由段組成。通常一個目标檔案中至少有兩個段:

代碼段:該段中所包含的主要是程式的指令。該段一般是可讀和可執行的,但一般卻不可寫。

資料段:主要存放程式中要用到的各種全局變量或靜态的資料。一般資料段都是可讀,可寫,可執行的。

連結

由彙程式設計式生成的目标檔案并不能立即就被執行,其中可能還有許多沒有解決的問題。

  例如,某個源檔案中的函數可能引用了另一個源檔案中定義的某個符号(如變量或者函數調用等);在程式中可能調用了某個庫檔案中的函數,等等。所有的這些問題,都需要經連結程式的處理方能得以解決。

  連結程式的主要工作就是将有關的目标檔案彼此相連接配接,也即将在一個檔案中引用的符号同該符号在另外一個檔案中的定義連接配接起來,使得所有的這些目标檔案成為一個能夠诶作業系統裝入執行的統一整體。

 我們在linux使用的gcc編譯器便是把以上的幾個過程進行捆綁,使使用者隻使用一次指令就把編譯工作完成,這的确友善了編譯工作,但對于初學者了解編譯過程就很不利了,下圖便是gcc代理的編譯過程:

 

C語言編譯與連結

參考自:

1.第二章——編譯和連結

2.C 編譯、連結、加載

3.C語言的編譯連結過程的介紹

繼續閱讀