標籤:
編譯過程主要分為4個過程
1) 編譯預先處理: 先行編譯程式完成的工作,可以說成是對來源程式的“替換”工作。經過這個過程,產生一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出檔案。
- 宏定義命令;例如#define
- 條件編譯指令;例如#ifdef
- 標頭檔包含指令;例如#include
- 特殊符號;例如__LINE__,__FILE__
- 預先處理模組;例如#pragma
2) 編譯、最佳化階段:通過詞法分析、文法分析,在確認所有的指令都符合文法規則之後,將其翻譯成等價的中間代碼或彙編代碼。在C++中,以下函數如果你沒有定義但是被需要時,編譯器會產生他們:預設建構函式、拷貝建構函式、解構函式、賦值運算子和一對取址運算子。
3) 彙編過程: 把組合語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個C語言來源程式,都將最終經過這一處理而得到相應的目標檔案。目標檔案中所存放的也就是與來源程式等效的目標的機器語言代碼。
4) 連結程式 :將有關的目標檔案彼此相串連,也即將在一個檔案中引用的符號同該符號在另外一個檔案中的定義串連起來,使得所有的這些目標檔案成為一個能夠誒作業系統裝入執行的統一整體。C++使用連結器以確保用到的函數都只被定義一次,以及確保static objects只被定義一次,會將我們做了聲明但卻未曾定義的函數檢測出來。連結有靜態連結和動態連結。
- 靜態連結:在這種連結方式下,函數的代碼將從其所在地靜態連結庫中被拷貝到最終的可執行程式中。這樣該程式在被執行時這些代碼將被裝入到該進程的虛擬位址空間中。靜態連結庫實際上是一個目標檔案的集合,其中的每個檔案含有庫中的一個或者一組相關函數的代碼。
- 動態連結:在此種方式下,函數的代碼被放到稱作是動態連結程式庫或共用對象的某個目標檔案中。連結程式此時所作的只是在最終的可執行程式中記錄下共用對象的名字以及其它少量的登記資訊。在此可執行檔被執行時,動態連結程式庫的全部內容將被映射到運行時相應進程的虛地址空間。動態連結程式將根據可執行程式中記錄的資訊找到相應的函數代碼。
備忘:標頭檔裡我們通常只放置聲明而不是定義,因為標頭檔有可能被釋放到多個源檔案中,每個源檔案都會單獨編譯,這樣連結時就會發現全域空間中有多個定義了。
C++編譯過程簡介