1. 程式人生 > >C++ —— C++程式編譯的四個過程

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”了,而這也就是連結的作用。