1. 程式人生 > 實用技巧 >gcc和g++理解

gcc和g++理解

環境使用的編譯器版本是是gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39)

編譯使用了c++11標準的程式時不能通過。

先放解決方法:g++-std=c++11 main.cpp -o main (一定要加c++11)

g++、gcc? 不懂就查

一、編譯的四個階段

  1. 預處理:編譯處理巨集定義等巨集命令(eg:#define)——生成字尾為“.i”的檔案   
  2. 編譯:將預處理後的檔案轉換成組合語言——生成字尾為“.s”的檔案   
  3. 彙編:由彙編生成的檔案翻譯為二進位制目標檔案——生成字尾為“.o”的檔案   
  4. 連線:多個目標檔案(二進位制)結合庫函式等綜合成的能直接獨立執行的執行檔案——生成字尾為“.out”的檔案

在我們理解了上述四個流程後,我們在關注gcc和g++在流程上的區別。
gcc無法進行庫檔案的連線,即無法編譯完成步驟4;而g++則能完整編譯出可執行檔案。(實質上,g++從步驟1-步驟3均是呼叫gcc完成,步驟4連線則由自己完成)

二、gcc 與g++的區別

首先說明:gcc 和 GCC 是兩個不同的東西
GCC:GNU Compiler Collection(GUN 編譯器集合),它可以編譯C、C++、JAV、Fortran、Pascal、Object-C、Ada等語言。


gcc是GCC中的GUN C Compiler(C 編譯器)
g++是GCC中的GUN C++ Compiler(C++編譯器)

誤區一:gcc只能編譯C程式碼,g++只能編譯c++程式碼。

事實上,二者都可以編譯c或cpp檔案。
gcc和g++的主要區別

  1. 對於.c和.cpp檔案,gcc分別當做c和cpp檔案編譯(cpp的語法規則比c的更強一些)
  2. 對於.c和.cpp檔案,g++則統一當做cpp檔案編譯
誤區二:編譯只能使用gcc,連線只能使用g++

這句話混淆了概念。編譯可以用 gcc 或 g++,而連結可以用 g++ 或者 gcc-lstdc++。
因為 gcc 命令不能自動和 C++ 庫連結,所以通常使用 g++ 來完成連結。


但在編譯階段,g++ 會自動呼叫 gcc,二者等價。

在編譯階段,g++會呼叫gcc,對於c++程式碼,兩者是等價的,但是因為gcc命令不能自動和C++程式使用的庫聯接,所以通常用g++來完成連結,為了統一起見,乾脆編譯/連結統統用g++了,這就給人一種錯覺,好像cpp程式只能用g++似的。

誤區三:extern “C” 與 gcc/g++ 有關係

實際上並無關係,
無論是 gcc 還是 g++,用 extern “c” 時,都是以 C 的命名方式來為symbol 命名,
否則,都以 C++ 方式為函式命名。

誤區四:gcc不會定義__cplusplus巨集,而g++會

實際上,這個巨集只是標誌著編譯器將會把程式碼按C還是C++語法來解釋,如上所述,如果字尾為.c,並且採用gcc編譯器,則該巨集就是未定義的,否則,就是已定義。

gcc在編譯.c檔案時,可使用的預定義巨集是比較少的,很多都是未定義的。
gcc在編譯cpp檔案時、g++在編譯c檔案和cpp檔案時(這時候gcc和g++呼叫的都是cpp檔案的編譯器),會加入一些額外的巨集,這些巨集如下:

#define __GXX_WEAK__ 1
#define __cplusplus 1
#define __DEPRECATED 1
#define __GNUG__ 4
#define __EXCEPTIONS 1
#define __private_extern__ extern

因此,我們總是會看到如下格式的程式碼(功能是對編譯器提示使用C的方式來處理函式):

其中,__cplusplus是c++定義的巨集,如果gcc在編譯cpp檔案時、g++在編譯c檔案和cpp檔案時,extern c宣告會有效。如果是gcc在編譯.c檔案時,那麼,extern c宣告無效。

#ifdef __cplusplus 
extern "C" { 
#endif

為什麼需要使用extern “C”呢?C++之父在設計C++之時,考慮到當時已經存在了大量的C程式碼,為了支援原來的C程式碼和已經寫好C庫,需要在C++中儘可能的支援C,而extern “C”就是其中的一個策略。

試想這樣的情況:一個庫檔案已經用C寫好了而且執行得很良好,這個時候我們需要使用這個庫檔案,但是我們需要使用C++來寫這個新的程式碼。如果這個程式碼使用的是C++的方式連結這個C庫檔案的話,那麼就會出現連結錯誤。

C和C++對函式的處理方式是不同的。extern“C”是使C++能夠呼叫C寫作的庫檔案的一個手段,如果要對編譯器提示使用C的方式來處理函式的話,那麼就要使用extern “C”來說明。

內容參考自:https://blog.csdn.net/u013457167/article/details/80222557