編譯鏈接是使用高級語言編程所必須的操作,一個源程序只有經過編譯、鏈接操作以後才可以變成計算機可以理解並執行的二進制可執行文件。
編譯是指根據用戶寫的源程序代碼,經過詞法和語法分析,將高級語言編寫的代碼轉變為功能有效的匯編代碼。
編譯過程如下:
1、 預編譯過程
在c語言的預編譯過程中,主要是對宏定義、條件編譯語句、頭文件包含語句以及特殊符號進行處理。
對於宏定義語句,比如#define NAME “user”,則在預編譯階段,會將程序中所有的NAME都替換為usr,當前有一點值得注意的是字符串中的NAME是不會被替換的。而#define語句在經過預編譯後的代碼中則不會出現。宏定義中還有一個#undef,對於它的處理是從取消的位置開始,後面的代碼中都不會進行替換了,同樣的經過預編譯後的代碼不會有#undef語句了。
對於條件編譯語句指的是#ifdef、#else、#ifndef、#elif、#endif、(注意還有#if)。條件編譯指的是——如果#ifdef debug,如果定義了debug,那麼後面部分的代碼就會被編譯,否則編譯#else後的代碼。對於條件編譯語句,在預編譯階段處理它,是根據它過濾掉那些不必要的代碼。
頭文件包含指令,之所以有頭文件是為了是某些定義可以讓更多的c源程序使用。在預編譯的過程中,預編譯程序會將頭文件中所有的定義都添加到它的輸出文件中去,而不再有頭文件包含指令。
2、 編譯的過程
經過預編譯以後,將產生新的源程序。編譯程序將通過詞法分析和語法分析,確認所有的指令都符合語法規則,並將其翻譯成等價的中間代碼或匯編代碼。
3、 優化及匯編過程
將匯編代碼翻譯成機器指令——即生成計算機系統可識別的二進制代碼。匯編的過程實際上就是將匯編語言代碼翻譯成為機器語言的過程。這時候生成的代碼實際上並不能直接運行,要經過鏈接以後才可以運行。
鏈接過程如下:
所謂鏈接的過程就是指,經過編譯後將會生成一個目標文件,這個目標文件可能會調用printf等函數,對於printf函數,它的目標代碼在系統的函數庫中(一般用戶用到的很多函數庫都存在於/usr/lib或者/lib中),鏈接所要做的就是將這些函數庫中相應的代碼組合到目標文件中去。
鏈接分為:
靜態鏈接;就是把函數庫中包含的目標代碼靜態添加到可執行文件中。一般靜態鏈接生成的文件比較大。可獨立運行。
動態鏈接;將這些函數庫的路徑、函數名等信息添加到可執行文件中去,在執行過程中動態加載函數庫。需要函數庫的支持。