一、GCC簡介
通常所說的GCC是GUN Compiler Collection的簡稱,除了編譯程序之外,它還含其他相關工具,所以它能把易於人類使用的高級語言編寫的源代碼構建成計算機能夠直接執行的二進制代碼。GCC是Linux平台下最常用的編譯程序,它是Linux平台編譯器的事實標准。同時,在Linux平台下的嵌入式開發領域,GCC也是用得最普遍的一種編譯器。GCC之所以被廣泛采用,是因為它能支持各種不同的目標體系結構。例如,它既支持基於宿主的開發(簡單講就是要為某平台編譯程序,就在該平台上編譯),也支持交叉編譯(即在A平台上編譯的程序是供平台B使用的)。目前,GCC支持的體系結構有四十余種,常見的有X86系列、Arm、PowerPC等。同時,GCC還能運行在不同的操作系統上,如Linux、Solaris、Windows等。
除了上面講的之外,GCC除了支持C語言,還支持多種其他語言,例如C++、Ada、Java、Objective-C、FORTRAN、Pascal、go等。
GCC的安裝:
Ubuntu等基於Debian發行版Linux可以使用如下命令安裝:
apt -get install gcc
Fedora等基於RPM發行版Linux可以使用如下命令安裝:
yum install gcc
使用如下命令查看gcc的版本:
gcc --version
本文地址:http://www.cnblogs.com/archimedes/p/linux-gcc.html,轉載請注明源地址。
二、程序的編譯過程
對於GUN編譯器來說,程序的編譯要經歷預處理、編譯、匯編、連接四個階段,如下圖所示:
從功能上分,預處理、編譯、匯編是三個不同的階段,但GCC的實際操作上,它可以把這三個步驟合並為一個步驟來執行。下面以C語言為例來談一下不同階段的輸入和輸出情況。
GCC編譯器的基本選項如下表:
類型 | 說明 |
-E | 預處理后即停止,不進行編譯、匯編及連接 |
-S | 編譯后即停止,不進行匯編及連接 |
-c | 編譯或匯編源文件,但不進行連接 |
-o file | 指定輸出文件file |
在預處理階段,輸入的是C語言的源文件,通常為*.c。它們通常帶有.h之類頭文件的包含文件。這個階段主要處理源文件中的#ifdef、 #include和#define命令。該階段會生成一個中間文件*.i,但實際工作中通常不用專門生成這種文件,因為基本上用不到;若非要生成這種文件不可,可以利用下面的示例命令:
gcc -E test.c -o test.i
在編譯階段,輸入的是中間文件*.i,編譯后生成匯編語言文件*.s 。這個階段對應的GCC命令如下所示:
gcc -S test.i -o test.s
在匯編階段,將輸入的匯編文件*.s轉換成機器語言*.o。這個階段對應的GCC命令如下所示:
gcc -c test.s -o test.o
最后,在連接階段將輸入的機器代碼文件*.s(與其它的機器代碼文件和庫文件)匯集成一個可執行的二進制代碼文件。這一步驟,可以利用下面的示例命令完成:
gcc test.o -o test
運行如下:
可以通過:cat -n [filename]命令查看每一個階段的文件內容
上面介紹了GCC編譯過程的四個階段以及相應的命令。下面我們進一步介紹常用的GCC的模式。
三、警告選項
GCC提供了大量的警告選項,對代碼中可能存在的問題提出警告,通常可以使用-Wall來開啟以下警告
GCC的編譯器警告選項如下表:
類型 | 說明 |
-Wall | 啟用所有警告信息 |
-Werror | 在發生警告時取消編譯操作,即將警告看作是錯誤 |
-w | 禁用所有警告信息 |
實例1:給出一段代碼,使用gcc進行編譯,同時開啟警告信息(test1.c)
#include<stdio.h> int main() { int i; for(i = 0; i <= 3; i++) printf("hello gcc!\n"); //return 0; }
使用-Wall開啟警告:
從上面可以看出,GCC給出了警告信息,意思是main函數的返回值被聲明為int,但是沒有返回值,GCC並不是簡單的發出警告,會中斷整個編譯過程
如果不想看到警告信息,可以使用-w來禁止所有的警告。
此外,GCC還提供了許多以-W開頭的選項,允許用戶指定輸出某個特定的警告,例如:
-
-Wcomment:出現注釋嵌套時發出警告。
-
-Wconversion:如果程序中存在隱式類型轉換,則發出警告。
-
-Wformat:檢查printf和scanf等格式化輸入輸出函數的格式字符串和參數類型的匹配情況,如果發現不匹配則發出警告。
-
-Winline:如果函數不能被內聯,則發出警告。
-
-Wlong-long:如果使用了long long型數據,則發出警告。
-
-Wmain:如果main函數的返回類型不是int型,或者調用main函數時使用的參數數目不正確,則發出警告。
-
-Wmissing-declarations:如果定義了全局函數,但卻沒有在頭文件中聲明,則發出警告。
-
-Wparentheses:在某些情況下,如果忽略掉了括號,則會發出警告。
-
-Wreturn-type:如果函數定義了返回類型,而默認類型是int型,編譯器會發出警告。
-
-Wuninitialized:如果使用的自動變量沒有被初始化,則發出警告。
-
-Wundef:如果在#if宏中使用了未定義的變量做判斷,則發出警告。
-
-Wunused:如果聲明的變量或static型函數沒有使用,則發出警告。
實例2:給出一段代碼,使用gcc進行編譯,同時開啟警告信息(test2.c)
#include<stdio.h> int main( ) { int a = 1; int b = 0; int c = 1; if(a && b || c) { ; } if(a == 1) if(b == 1) printf("b = 1\n"); else printf("b != 1\n"); return 0; }
使用-Wparentheses開啟警告:
四、優化選項
GCC具有優化代碼的功能,主要的優化選項包括如下:
- -O0:不進行優化處理。
- -O或-O1:進行基本的優化,這些優化在大多數情況下都會使程序執行得更快。
- -O2:除了完成-O1級別的優化外,還要一些額外的調整工作,如處理器指令調度等,這是GNU發布軟件的默認優化級別。√
- -O3:除了完成-O2級別的優化外,還進行循環的展開以及其他一些與處理器特性相關的優化工作。
- -Os:生成最小的可執行文件,主要用於在嵌入式領域。
一般來說,優化級別越高,生成可執行文件的運行速度也越快,但消耗在編譯上的時間就越長,因此在開發的時候最好不要使用優化選項,到軟件發行或開發結束的時候才考慮對最終生成的代碼進行優化。
- -finline-functions:允許編譯器將一些簡單的函數在其調用處展開。
- -funswitch-loops:將循環體中值不改變的變量移到循環體外。
實例:給出一段代碼,使用gcc進行編譯,同時比較優化前后執行程序所花的時間(test3.c)
#include<stdio.h> int main() { int i, j, x; x = 0; for(i = 0; i < 100000; i++) { for(j = i; j > 0; j--) { x += j; } } return 0; }
運行后的結果如下:
可以看到,優化的效果十分的顯著