gcc/g++ 實戰之編譯的過程

本文轉載自: https://www.cnblogs.com/zjiaxing/p/5557549.html

gcc和g++分別是GNU(一個開源組織)的c&c++編譯器
 

對於.c後綴的文件,gcc把它當做是C程序,g++當做是C++程序;對於.cpp後綴的文件,gcc和g++都會當做c++程序。gcc可以根據後綴名爲.c或.cpp分別按c程序和c++程序來編譯,但是g++無論是.c或.cpp都統一按c++程序來編譯。

 

編譯階段,g++會調用gcc,鏈接階段通常會用g++來完成,g++在編譯的過程中,其實是調用gcc按照c++程序來編譯的。即編譯工作最終都是由gcc來完成的。這是因爲gcc命令不能自動和c++程序使用的庫連接。而g++則會自動調用鏈接的c++庫。

gcc可以用來編譯c++但是它不會自動調用鏈接的c++庫,你需要自己手動鏈接,使用如下命令:

gcc main.cpp -lstdc++

注:main.cpp -lstdc++ 位置不能換,換了位置筆者編譯出現了 main.cpp:(.text+0x2d):undefined reference to`std::cout' 等一系列的錯誤


gcc/g++在執行編譯工作的時候,分爲以下四個過程:

1.預處理,生成.i的文件
2.將預處理後的文件轉換成彙編語言,生成.s文件
3.彙編變爲目標代碼(機器代碼)生成.o的文件
4.連接目標代碼,生成可執行程序

下面用個小例子說明這四個過程:

 //建個main.cpp
複製代碼
//This is the test code
 #include <iostream>
 using namespace std;  
 #define pi 3.14
 static int t = 1; 

 int main()
 {
    cout<<"Hello World: The t+pi is "<<t+pi<<endl;
    return 0;
  } 
複製代碼

(1)預處理階段

g++ -E main.cpp > main.i 

預處理後的文件 linux下以.i爲後綴名,這個過程只激活預處理,不生成文件,因此你需要把它重定向到一個輸出文件裏 。

這一步的功能:

宏的替換,還有註釋的消除,還有找到相關的庫文件,#include文件的全部內容插入。若用<>括起文件則在系統的INCLUDE目錄中尋找文件,若用" "括起文件則在當前目錄中尋找文件。

用編輯器打開main.i會發現有很多很多代碼,你只需要看最後部分就會發現,預處理做了宏的替換,還有註釋的消除,可以理解爲無關代碼的清除。

cat main.i

下面是main.i文件的最後部分,可以看見宏的替換和註釋的消除。

 

(2)將預處理後的文件轉換成彙編語言,生成.s文件

g++ -S main.cpp

這一步的功能:

生成main.s文件,.s文件表示是彙編文件,用編輯器打開就都是彙編指令。

cat main.s

下面是main.s文件的一部分:

(3)彙編變爲目標代碼(機器代碼)生成.o的文件

g++ -c main.cpp 

這一步的功能:

.o是gcc生成的目標文件,用編輯器打開就都是二進制機器碼。
 
cat main.o

下面是main.o文件的一部分:

(4)連接目標代碼,生成可執行程序

g++ main.o -o main //生成的可執行程序名爲main ,如果執行命令 g++ main.o  這樣默認生成a.out,也就是main與a.out是一個只是名字不同而已
下面是main文件的一部分:
 
 
ls

./main

在成功編譯之後,就進入了鏈接階段。在這裏涉及到一個重要的概念:函數庫(可以這麼理解就是不帶main()函數的.cpp生成的)。

讀者可以重新查看這個小程序,在這個程序中並沒有定義”cout”的函數(準確說cout不是函數,cout卻很獨特:既不是函數,似乎也不是C++特別規定出來的像if,for一類有特殊語法的“語句”,其實說到底還是函數調用,不過這函數有些特殊,用的是運算符重載,確切地說是重載了“<<”運算符。這裏如果用pritf()函數說明會更好,暫且當做函數理解吧)實現,且在預編譯中包含進的”iostream”中也只有該函數的聲明,而沒有定義函數的實現,那麼,是在哪裏實現”cout”函數的呢?系統把這些函數實現都被做到名爲stdc++的庫文件中去了,在沒有特別指定時,g++會到系統默認的搜索路徑”/usr/lib”下進行查找,也就是鏈接到stdc++庫函數中去,這樣就能實現函數”cout”了,而這也就是鏈接的作用。

函數庫一般分爲靜態庫和動態庫兩種。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章