1.gcc
GNU編譯器套件(GNU Compiler Collection)原名為GNU C語言編譯器(GNU C Compiler),因為它原本只能處理C語言。GCC在發佈後很快地得到擴展,包括C、C++、Objective-C、Fortran、Java、Ada和Go語言的前端,也包括了這些語言的庫(如libstdc++、libgcj等等)。GCC的初衷是爲GNU操作系統專門編寫的一款編譯器。GNU系統是徹底的自由軟件。此處,“自由”的含義是它尊重用戶的自由。
GUN 編譯器套件包含多種前端處理器,以翻譯各種不同語言。當然,我們重點討論的是基於C語言的前端處理器 GCC。
GCC 也是一種多目標(multitarget)編譯器;換句話說,它通過使用可互換的後端處理器,爲多種不同的計算機架構生成相應的可執行程序。
GCC 不僅支持C的許多“方言”,也可以區別不同的C語言標準;也就是說,可以使用命令行選項來控制編譯器在翻譯源代碼時應該遵循哪個C標準。例如,當使用命令行參數
-std=c99
啓動 GCC 時,編譯器支持 C99 標準。GUN99 c99
1.1 安裝
-
安裝命令
sudo apt install gcc g++ # 在Linux中寫程序: gcc版本 > 4.8.5
-
查看版本
gcc -v/--version g++ -v/--version
-
gcc與g++有什麼區別?
gcc和g++都是GNU(組織)的一個編譯器。
-
誤區一:gcc只能編譯c代碼,g++只能編譯c++代碼。兩者都可以,但是請注意:
- 後綴爲.c的,gcc把它當作是C程序,而g++當作是c++程序;
- 後綴爲.cpp的,兩者都會認爲是c++程序,C++的語法規則更加嚴謹一些。
- 編譯階段,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,二者等價
- 嚴格來說,這句話不算錯誤,但是它混淆了概念,應該這樣說:編譯可以用gcc/g++,而鏈接可以用
-
1.2 gcc 工作流程
GCC 編譯器在編譯一個C語言程序時需要經過以下 4 步:
- 將C語言源程序預處理,生成
.i
文件。
- 頭文件展開
- 宏替換
- define NUM 10
- int a = NUM
- 註釋刪除
- xxx.c -> xxx.i
- gcc -E xxx.c -o xxx.i
- 預處理後的.i文件編譯成爲彙編語言,生成
.s
文件。
- xxx.i -> xxx.s (得到彙編文件)
- gcc -S xxx.i -o xxx.s
- 將彙編語言文件經過彙編,生成目標文件
.o
文件。
- xxx.s -> xxx.o (二進制文件)
- gcc -c xxx.s -o xxx.o
- 將各個模塊的
.o
文件鏈接起來生成一個可執行程序文件。
- xxx.o -> 可執行程序 (二進制的)
- gcc xxx.o -o xxx
1.3 gcc常用參數選項
gcc編譯選項 | 選項的意義 |
---|---|
-E | 預處理指定的源文件,不進行編譯 |
-S | 編譯指定的源文件,但是不進行彙編 |
-c | 編譯、彙編指定的源文件,但是不進行鏈接 |
-o [file1] [file2] / [file2] -o [file1] | 將文件 file2 編譯成可執行文件 file1 |
-I directory | 指定 include 包含文件的搜索目錄 |
-g | 在編譯的時候,生成調試信息,該程序可以被調試器調試 |
-D | 在程序編譯的時候,指定一個宏 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-On | n的取值範圍:0~3。編譯器的優化選項的4個級別,-O0表示沒有優化,-O1爲缺省值,-O3優化級別最高 |
-l | 在程序編譯的時候,指定使用的庫 |
-L | 指定編譯的時候,搜索的庫的路徑。 |
-fPIC/fpic | 生成與位置無關的代碼 |
-shared | 生成共享目標文件。通常用在建立共享庫時 |
-std | 指定C方言,如:-std=c99,gcc默認的方言是GNU C |
參數 -D 使用場景: 程序調試的時候使用, 通過-D指定的宏打開log輸出
#include <stdio.h>
//#define DEBUG
int main()
{
int a = 10;
#ifdef DEBUG
printf("我是一個程序猿, 我不會爬樹...\n");
#endif
for(int i=0; i<3; ++i)
{
printf("hello, GCC!!!\n");
}
return 0;
}
默認編譯第7行代碼不輸出, 如果想要輸出這句話, 可以使用-D
參數 -On 優化程序, 有4個級別
n 取值範圍: 0-3
O0 -> 不優化, O1 -> 默認的級別, O3 -> 最高級別
最簡單的例子:
int a, b, c, d;
a = 10;
b = a;
c = b;
d = c;
// 優化:
b = 10;
c = 10;
d = 10;
參數 -std , 指定編譯器規範
c最早的標準:c89
c99開始支持現在的書寫習慣
int a = 10;
func();
int b =5;
for(int i=0; i<5; ++i)
gcc -std=c99/gnu99 test.c -o test
-DDEBUG 參數和值直接的空格可有可無
gcc test.c -o test -DDEBUG # define DEBUG