c編譯器的問世是程序界的里程碑之一,沒有c編譯器,c程序將無法運行。由此可見,c編譯器尤為重要。為增進大家對c編譯器的了解,本文將帶來c編譯器的通識篇,以使大家能夠了解編譯器的運行過程。此外,本文僅為上篇,剩余內(nèi)容將在后期文章中補充講解。如果你對本文即將探討的內(nèi)容存在一定興趣,不妨繼續(xù)往下閱讀。
一、編譯器介紹
簡單講,編譯器就是將“一種語言(通常為高級語言)”翻譯為“另一種語言(通常為低級語言)”的程序。一個現(xiàn)代編譯器的主要工作流程:源代碼 (source code) → 預處理器 (preprocessor) → 編譯器 (compiler) → 目標代碼 (object code) → 鏈接器 (Linker) → 可執(zhí)行程序(executables)
二、編譯器的種類
編譯器可以生成用來在與編譯器本身所在的計算機和操作系統(tǒng)(平臺)相同的環(huán)境下運行的目標代碼,這種編譯器又叫做“本地”編譯器。另外,編譯器也可以生成用來在其它平臺上運行的目標代碼,這種編譯器又叫做交叉編譯器。交叉編譯器在生成新的硬件平臺時非常有用?!霸创a到源碼編譯器”是指用一種高級語言作為輸入,輸出也是高級語言的編譯器。例如:自動并行化編譯器經(jīng)常采用一種高級語言作為輸入,轉換其中的代碼,并用并行代碼注釋對它進行注釋(如OpenMP)或者用語言構造進行注釋(如FORTRAN的DOALL指令)。
三、編譯器工作原理
編譯是從源代碼(通常為高級語言)到能直接被計算機或虛擬機執(zhí)行的目標代碼(通常為低級語言或機器語言)的翻譯過程。然而,也存在從低級語言到高級語言的編譯器,這類編譯器中用來從由高級語言生成的低級語言代碼重新生成高級語言代碼的又被叫做反編譯器。也有從一種高級語言生成另一種高級語言的編譯器,或者生成一種需要進一步處理的的中間代碼的編譯器(又叫級聯(lián))。
典型的編譯器輸出是由包含入口點的名字和地址,以及外部調用(到不在這個目標文件中的函數(shù)調用)的機器代碼所組成的目標文件。一組目標文件,不必是同一編譯器產(chǎn)生,但使用的編譯器必需采用同樣的輸出格式,可以鏈接在一起并生成可以由用戶直接執(zhí)行的EXE,
所以我們電腦上的文件都是經(jīng)過編譯后的文件。
四、編譯器的工作過程
源碼要運行,必須先轉成二進制的機器碼,這是編譯器的任務。比如,下面這段源碼(假定文件名叫做test.c)。
#include 《stdio.h》
int main(void)
{
fputs(“Hello, world!\n”, stdout);
return 0;
}
要先用編譯器處理一下,才能運行。
$ gcc test.c
$ 。/a.out
Hello, world!
對于復雜的項目,編譯過程還必須分成三步。
$ 。/configure
$ make
$ make install
本文將介紹編譯器的工作過程,也就是上面這三個命令各自的任務。我主要參考了Alex Smith的文章《Building C Projects》。需要聲明的是,本文主要針對gcc編譯器,也就是針對C和C++,不一定適用于其他語言的編譯。
1.第一步 配置(configure)
編譯器在開始工作之前,需要知道當前的系統(tǒng)環(huán)境,比如標準庫在哪里、軟件的安裝位置在哪里、需要安裝哪些組件等等。這是因為不同計算機的系統(tǒng)環(huán)境不一樣,通過指定編譯參數(shù),編譯器就可以靈活適應環(huán)境,編譯出各種環(huán)境都能運行的機器碼。這個確定編譯參數(shù)的步驟,就叫做“配置”(configure)。
這些配置信息保存在一個配置文件之中,約定俗成是一個叫做configure的腳本文件。通常它是由autoconf工具生成的。編譯器通過運行這個腳本,獲知編譯參數(shù)。
configure腳本已經(jīng)盡量考慮到不同系統(tǒng)的差異,并且對各種編譯參數(shù)給出了默認值。如果用戶的系統(tǒng)環(huán)境比較特別,或者有一些特定的需求,就需要手動向configure腳本提供編譯參數(shù)。
$ 。/configure --prefix=/www --with-mysql
上面代碼是php源碼的一種編譯配置,用戶指定安裝后的文件保存在www目錄,并且編譯時加入mysql模塊的支持。
2.第二步 確定標準庫和頭文件的位置
源碼肯定會用到標準庫函數(shù)(standard library)和頭文件(header)。它們可以存放在系統(tǒng)的任意目錄中,編譯器實際上沒辦法自動檢測它們的位置,只有通過配置文件才能知道。
編譯的第二步,就是從配置文件中知道標準庫和頭文件的位置。一般來說,配置文件會給出一個清單,列出幾個具體的目錄。等到編譯時,編譯器就按順序到這幾個目錄中,尋找目標。
3.第三步 確定依賴關系
對于大型項目來說,源碼文件之間往往存在依賴關系,編譯器需要確定編譯的先后順序。假定A文件依賴于B文件,編譯器應該保證做到下面兩點。
編譯順序保存在一個叫做makefile的文件中,里面列出哪個文件先編譯,哪個文件后編譯。而makefile文件由configure腳本運行生成,這就是為什么編譯時configure必須首先運行的原因。
在確定依賴關系的同時,編譯器也確定了,編譯時會用到哪些頭文件。
以上便是此次小編帶來的“c編譯器”相關內(nèi)容,希望大家對本文講解的內(nèi)容具備一定的認知。如果你喜歡本文,不妨持續(xù)關注我們網(wǎng)站哦,小編將于后期帶來更多精彩內(nèi)容。最后,十分感謝大家的閱讀,have a nice day!





