C++ —— C++程式編譯的四個過程
C++ —— C++程式編譯的四個過程
g++是Linux下C++的編譯器;我為什麼會選擇Linux下的g++編譯器,就是因為g++可以看到程式從編譯到執行的過程做了些什麼。而VS等整合開發環境看不到這些,並不是說VS工具不好,(VS還是相當好用的...)。對於學習來說,需要知道程式從編譯到執行進行了哪些工作,做了哪些事情,首推g++編譯器(這個看個人習慣)。
一、常見檔案字尾
.c為字尾的檔案:c語言原始碼檔案
.a為字尾的檔案:是由目標檔案構成的庫檔案
.C,.cc為字尾的檔案:是c++原始碼檔案
.h為字尾的檔案:標頭檔案
o為字尾的檔案:是編譯後的目標檔案
.s為字尾的檔案:是組合語言原始碼檔案
.m為字尾的檔案:Objective-C原始程式
.so為字尾的檔案:編譯後的動態庫檔案
二、g++執行的四個過程
1、預處理:條件編譯,標頭檔案包含,巨集替換的處理,生成.i檔案。
2、編譯:將預處理後的檔案轉換成組合語言,生成.s檔案
3、彙編:彙編變為目的碼(機器程式碼)生成.o的檔案
4、連結:連線目的碼,生成可執行程式
三、最簡單的C++程式——"helloworld!\n"
// 新建hello.cpp檔案,vim編輯 #include <iostream> using namespace std; int main(void) { count << "hello world!"<< endl; reutrn 0; }
(1)預處理階段
g++ -E hello.cpp > hello.i
通過vim開啟hello.i檔案,你會發現一些情況(最好是自己觀察,看看哪些內容被換了);
巨集的替換,還有註釋的消除,還有找到相關的庫檔案,將#include檔案的全部內容插入。若用<>括起檔案則在系統的INCLUDE目錄中尋找檔案,若用""括起檔案則在當前目錄中尋找檔案。
用編輯器開啟hello.i會發現有很多很多程式碼,你只需要看最後部分就會發現,預處理做了巨集的替換,還有註釋的消除,可以理解為無關程式碼的清除。
(2)編譯
g++ -S hello.cpp
生成hello.s檔案,.s檔案表示是彙編檔案,用編輯器開啟就都是彙編指令。(可以通過vim編輯器看看hello.s裡面的內容【都是彙編指令,哈哈】)。
(3)彙編
g++ -c hello.cpp
彙編變為目的碼(機器程式碼)生成.o的檔案,.o是gcc生成的目標檔案,用編輯器開啟就都是二進位制機器碼。
(4)連結 ——連結生成可執行檔案(庫檔案進行連結)
g++ -o hello hello.cpp
程式執行:./hello【輸出hello world!】
在成功編譯之後,就進入了連結階段。在這裡涉及到一個重要的概念:函式庫(可以這麼理解就是不帶main()函式的.cpp生成的)。
可以重新檢視這個小程式,在這個程式中並沒有定義”cout”的函式(準確說cout不是函式,cout卻很獨特:既不是函式,似乎也不是C++特別規定出來的像if,for一類有特殊語法的“語句”,其實說到底還是函式呼叫,不過這函式有些特殊,用的是運算子過載,確切地說是過載了“<<”運算子。這裡如果用pritf()函式說明會更好,暫且當做函式理解吧)實現,且在預編譯中包含進的”iostream”中也只有該函式的宣告,而沒有定義函式的實現,那麼,是在哪裡實現”cout”函式的呢?系統把這些函式實現都被做到名為stdc++的庫檔案中去了,在沒有特別指定時,g++會到系統預設的搜尋路徑”/usr/lib”下進行查詢,也就是連結到stdc++庫函式中去,這樣就能實現函式”cout”了,而這也就是連結的作用。