編譯原理
如圖
預編譯階段
在預編譯階段,發揮作用的是預處理器(cpp)。預處理器讀取.cpp檔案,對其中的偽指令(#開頭的指令)和特殊符號進行處理,特別的,對#include指令進行遞迴處理,包含需要的標頭檔案。
常見的偽指令有#define、#include""(包括你需要的標頭檔案),在你的預處理器處理過後,會將你#include的標頭檔案中的**內容(不包括預處理的內容)替換到你的.cpp檔案中,也會將你#define的內容替換,會選擇你條件編譯(#if #else #endif)的**塊等彙總成乙個新的原始檔。
預處理階段還會將注釋刪除
新增行號和檔名標識,方便除錯使用
特例:保留所有的#pragma指令,因為編譯器需要使用
此時源程式還是文字檔案。
###編譯階段
在這個階段中,編譯器(cc1)會進行語法分析、語義分析、詞法分析、優化、將原始檔轉換為組合語言,組合語言還是文字檔案,但cpu無法理解文字檔案。
###彙編階段
在這個階段,發揮作用的是彙編器(as),彙編器會將組合語言翻譯成機器語言,機器只會識別二進位制,所以機器語言為二進位制。window平台上是.obj檔案,linux是.o檔案,為可重定位的目標檔案。
###鏈結階段
這個階段發揮作用的是聯結器(ld),鏈結器會將所有的.obj檔案鏈結到一起,成為可執行的.exe檔案。鏈結時會將程式引用的庫與自己生成的.obj檔案一起鏈結成為可執行檔案,這樣的鏈結方式就叫做靜態鏈結。但是存在乙個問題,如果你的應用程式使用了很多庫,靜態鏈結會將所有的庫鏈結到你的.obj檔案中,最終形成很大的.exe程式,不利於以後程式的更新。所以就出現了動態鏈結。
動態鏈結,動態庫在鏈結階段不會被鏈結到.obj檔案中,應該只是(我也不確定)將你用到的api的位址等一系列資訊和你的.obj檔案鏈結起來,形成.exe檔案,在你的exe程式執行時才載入這個動態庫檔案,這樣,就大大減少了你的應用程式的大小,方便更新等一系列優點。
###生成exe
這樣,你的exe就生成了。
##注意點
###防止多重包含
在預處理階段,你會經常看到#ifndef #define #endif。這是為了防止重複包含。在預處理器第一次處理這個標頭檔案時,會#define乙個巨集,當其他檔案再次包含這個標頭檔案時,預處理器檢測到這個巨集,會直接跳過這段**,這樣就不會出現重複**
###.h和.cpp檔案
在編譯成.obj檔案時,乙個.h和對應的.cpp會形成乙個.obj檔案,你的工程中如果有多個.h和.cpp檔案,就會生成多個.obj檔案,例如乙個c_object類的.h和.cpp檔案將會生成乙個.obj檔案,此時已經成為機器語言的.obj檔案,將會在鏈結時將會鏈結到一起生成可執行檔案。
###例子
b.**件
b.cpp檔案
global.**件
global.cpp檔案
main.cpp檔案
程式很簡單,但是如果我要注釋掉extern int i;ide會報什麼樣的錯誤呢?
我們推斷一下,首先在預處理階段不會報錯,三個cpp檔案會將他們包含的標頭檔案的**部分在分別的.cpp檔案展開,成為新的文字檔案。
在編譯階段也不會出錯,因為沒有語法錯誤,新的原始檔會被編譯成組合語言,此時還是乙個文字檔案,此時應該還定義了程式中的變數應該申請多少記憶體,在程式執行時向系統索要記憶體。
在彙編階段將會轉化為a.obj、b.obj、gobal.obj,main.obj,此時為二進位制,為機器語言。
鏈結階段,應該為將四個檔案鏈結到一起,a.obj中包括乙個整形的i被定義,b.obj中也有乙個i被定義,global.obj也有乙個i被定義,鏈結到一起時檢測到多個相同名稱的變數存在,出錯!報錯為找到乙個或多個多重符號的定義。所以要在global.**件中宣告i,這樣聯結器檢測到i為乙個宣告,在不同的obj檔案中進行賦值。通過編譯。
那在global.**件中宣告乙個函式,在.cpp檔案實現,編譯器會不會說函式多重定義呢?答案是不會,因為函式宣告和定義的方式不一樣,而變數的宣告和定義如果不加extern關鍵字則會一樣,無法辨別變數是宣告還是定義,所以要有extern的存在。
i 可以編譯新增多個 C語言的編譯過程
大家對c語言的編譯過程可能有個大致的理解,但是,詳細到每一步具體都幹了啥,可能有的人不是很清楚啦,也包括我,要不然,就不會做筆記了,哈哈.步驟 編寫源程式 c 預處理 編譯 彙編 鏈結 中間檔案 圖1 編譯流程 注 gcc的目標檔案 機器碼 的字尾是 o visual c 的目標檔案的字尾是 obj...
模仿JQuery 的新增多個事件的原理
var jquery function dom else return obj window.onload function jquery window ready function 說到底原理上還是覆蓋了 只是第一次執行函式的的時候 old dom.onload 是乙個空函式 它肯定也執行了 就是...
編譯原理詞法分析
編譯原理實驗一 詞法分析練習 include include include define tokenmax 100 define progmax 1000 define k esc 27 void analytics 詞法分析 void scanner 輸入掃瞄 bool isletter cha...