GNU gcc 和 g++ 的區別詳解
阿新 • • 發佈:2019-02-15
gcc 和 g++ 都是 GNU 組織的編譯器。
誤區一: gcc 只能編譯 C 程式碼,g++ 只能編譯 C++ 程式碼
兩者都可以,但是請注意:
1. 字尾為 .c 的,gcc 把它當作是 C 程式,而 g++ 當作是 C++ 程式;
字尾為.cpp的,兩者都會認為是 C++程式;
注意: 雖然 C++ 是 C 的超集,但是兩者對語法的要求是有區別的! C++ 的語法規則更加嚴謹一些。
例如:
如果按照 C 的語法規則,OK,沒問題,但是,一旦把字尾改為 .cpp,立刻報三個錯:
“printString未定義”;
“cannot convert `char**' to `char*”;
“return-statement with no value”;
可見C++的語法規則更加嚴謹一些。
2. 編譯階段,g++ 會呼叫 gcc,對於 C++ 程式碼,兩者是等價的,
但是因為 gcc 命令不能自動和 C++ 庫連結,所以通常用 g++ 來完成連結,
為了統一,乾脆編譯與連結統統用 g++ 了,就給人一種錯覺,好像 cpp 程式只能用 g++ 似的。
誤區二: gcc 不會定義 __cplusplus 巨集,而 g++ 會
實際上,這個巨集只是標誌著編譯器將會把程式碼按 C 還是 C++ 語法來解釋,
如上所述,如果字尾為 .c,並且採用 gcc 編譯器,則該巨集就是未定義的,否則,就是已定義。
誤區三: 編譯只能用 gcc,連結只能用 g++
嚴格來說,這句話不算錯誤,但是它混淆了概念,應該這樣說:
編譯可以用 gcc 或 g++,而連結可以用 g++ 或者 gcc -lstdc++。
因為 gcc 命令不能自動和 C++ 庫連結,所以通常使用 g++ 來完成連結。
但在編譯階段,g++ 會自動呼叫 gcc,二者等價。
誤區四: extern "C" 與 gcc 或 g++ 有關係
實際上並無關係,
無論是 gcc 還是 g++,用 extern "c" 時,都是以 C 的命名方式來為 函式 命名,
否則,都以 C++ 方式為 函式 命名。
試驗如下:
test.h:
extern "C" void CppPrintf(void);
test.cpp:
#include <iostream>
#include "test.h"
using namespace std;
void
CppPrintf( void )
{
cout << "Hellon";
}
main.cpp:
#include <stdlib.h>
#include <stdio.h>
#include "test.h"
int
main( void )
{
CppPrintf();
return 0;
}
1. 先給 test.h 裡的 void CppPrintf(void); 加上 extern "C",看用 gcc 和 g++ 命名有什麼不同。
$ g++ -S test.cpp
$ less test.s
.globl CppPrintf <-- 注意此函式的命名
.type CppPrintf, @function
$ gcc -S test.cpp
$ less test.s
.globl CppPrintf <-- 注意此函式的命名
.type CppPrintf, @function
完全相同!
2. 去掉 test.h 裡 void CppPrintf(void); 前面的 extern "C",看用 gcc 和 g++ 命名有什麼不同。
結論:
完全相同,可見 extern "C" 與採用 gcc 或 g++ 並無關係,
誤區一: gcc 只能編譯 C 程式碼,g++ 只能編譯 C++ 程式碼
兩者都可以,但是請注意:
1. 字尾為 .c 的,gcc 把它當作是 C 程式,而 g++ 當作是 C++ 程式;
字尾為.cpp的,兩者都會認為是 C++程式;
注意: 雖然 C++ 是 C 的超集,但是兩者對語法的要求是有區別的! C++ 的語法規則更加嚴謹一些。
例如:
#include <stdio.h>
int
main( int argc,
char *argv[] )
{
if (
0
==
argv
)
{
return;
}
printString( argv );
return;
}
int
printString( char* string )
{
sprintf( string,
"This is a test.n" );
}
如果按照 C 的語法規則,OK,沒問題,但是,一旦把字尾改為 .cpp,立刻報三個錯:
“printString未定義”;
“cannot convert `char**' to `char*”;
“return-statement with no value”;
可見C++的語法規則更加嚴謹一些。
2. 編譯階段,g++ 會呼叫 gcc,對於 C++ 程式碼,兩者是等價的,
但是因為 gcc 命令不能自動和 C++ 庫連結,所以通常用 g++ 來完成連結,
為了統一,乾脆編譯與連結統統用 g++ 了,就給人一種錯覺,好像 cpp 程式只能用 g++ 似的。
誤區二: gcc 不會定義 __cplusplus 巨集,而 g++ 會
實際上,這個巨集只是標誌著編譯器將會把程式碼按 C 還是 C++ 語法來解釋,
如上所述,如果字尾為 .c,並且採用 gcc 編譯器,則該巨集就是未定義的,否則,就是已定義。
誤區三: 編譯只能用 gcc,連結只能用 g++
嚴格來說,這句話不算錯誤,但是它混淆了概念,應該這樣說:
編譯可以用 gcc 或 g++,而連結可以用 g++ 或者 gcc -lstdc++。
因為 gcc 命令不能自動和 C++ 庫連結,所以通常使用 g++ 來完成連結。
但在編譯階段,g++ 會自動呼叫 gcc,二者等價。
誤區四: extern "C" 與 gcc 或 g++ 有關係
實際上並無關係,
無論是 gcc 還是 g++,用 extern "c" 時,都是以 C 的命名方式來為 函式 命名,
否則,都以 C++ 方式為 函式 命名。
試驗如下:
test.h:
extern "C" void CppPrintf(void);
test.cpp:
#include <iostream>
#include "test.h"
using namespace std;
void
CppPrintf( void )
{
cout << "Hellon";
}
main.cpp:
#include <stdlib.h>
#include <stdio.h>
#include "test.h"
int
main( void )
{
CppPrintf();
return 0;
}
1. 先給 test.h 裡的 void CppPrintf(void); 加上 extern "C",看用 gcc 和 g++ 命名有什麼不同。
$ g++ -S test.cpp
$ less test.s
.globl CppPrintf <-- 注意此函式的命名
.type CppPrintf, @function
$ gcc -S test.cpp
$ less test.s
.globl CppPrintf <-- 注意此函式的命名
.type CppPrintf, @function
完全相同!
2. 去掉 test.h 裡 void CppPrintf(void); 前面的 extern "C",看用 gcc 和 g++ 命名有什麼不同。
$
g++ -S test.cpp
$
less test.s
.globl _Z9CppPrintfv
<--
注意此函式的命名.type _Z9CppPrintfv,
@function
$ gcc -S test.cpp
$ less test.s
.globl _Z9CppPrintfv
<--
注意此函式的命名
.type _Z9CppPrintfv, @function
完全相同!
結論:
完全相同,可見 extern "C" 與採用 gcc 或 g++ 並無關係,
以上的試驗還間接的印證了前面的說法:在編譯階段,g++ 是呼叫 gcc 的。
補充:gcc和g++在程式設計的時候平時覺的區別就是結構體的定義
對了,當我使用GCC編譯的時候,編譯器返回的錯誤是在我的結構體設計的部分。 typedef struct NodeTrie { NodeTrie *p; ……; } 總是會說我的第二個NodeTrie是沒有定義的,但是使用了G++之後,問題解決。
按照c的寫法 第二個NodeTrie *p應當寫成struct NodeTrie *p,按照c++的寫法實際不需要typedef了,struct與class的唯一區別就是成員變數前者預設public後者預設private 。
c的語法在NodeTrie *p這個時候 由於還沒走到右花括號那個NodeTrie ,也就是說typedef還沒有完成,那麼自然他不認識NodeTrie 這是什麼東西,只認識struct NodeTrie