GCC簡介
Linux系統下的gcc(GNU C Compiler)是GNU推出的功能強大、性能優越的多平台編譯器,是GNU的代表作品之一。gcc是可以在多種硬體平台上編譯出可執行程序的超級編譯器,其執行效率與一般的編譯器相比平均效率要高20%~30%。gcc編譯器能將C、C++語言源程序、匯程式化序和目標程序編譯、連接成可執行文件,如果沒有給出可執行文件的名字,gcc將生成一個名為a.out的文件。
在Linux系統中,可執行文件沒有統一的后綴,系統從文件的屬性來區分可執行文件和不可執行文件。而gcc則通過后綴來區別輸入文件的類別,下面我們來介紹gcc所遵循的部分約定規則。
.c為后綴的文件,C語言源代碼文件;
.a為后綴的文件,是由目標文件構成的檔案庫文件;
.C,.cc或.cxx 為后綴的文件,是C++源代碼文件;
.h為后綴的文件,是程序所包含的頭文件;
.i 為后綴的文件,是已經預處理過的C源代碼文件;
.ii為后綴的文件,是已經預處理過的C++源代碼文件;
.m為后綴的文件,是Objective-C源代碼文件;
.o為后綴的文件,是編譯后的目標文件;
.s為后綴的文件,是匯編語言源代碼文件;
.S為后綴的文件,是經過預編譯的匯編語言源代碼文件。
gcc的執行過程
雖然我們稱gcc是C語言的編譯器,但使用gcc由C語言源代碼文件生成可執行文件的過程不僅僅是編譯的過程,而是要經歷四個相互關聯的步驟∶預處理(也稱預編譯,Preprocessing)、編譯(Compilation)、匯編(Assembly)和連接(Linking)。命令gcc首先調用cpp進行預處理,在預處理過程中,對源代碼文件中的文件包含(include)、預編譯語句(如宏定義define等)進行分析。接着調用cc1進行編譯,這個階段根據輸入文件生成以.o為后綴的目標文件。匯編過程是針對匯編語言的步驟,調用as進行工作,一般來講,.S為后綴的匯編語言源代碼文件和匯編、.s為后綴的匯編語言文件經過預編譯和匯編之后都生成以.o為后綴的目標文件。當所有的目標文件都生成之后,gcc就調用ld來完成最后的關鍵性工作,這個階段就是連接。在連接階段,所有的目標文件被安排在可執行程序中的恰當的位置,同時,該程序所調用到的庫函數也從各自所在的檔案庫中連到合適的地方。
一、預處理(生成預編譯文件 ,.i文件)
gcc –E hello.c –o hello.i //一定.c作為后綴,讓gcc識別
預處理過程主要處理那些源代碼中以#開始的預編譯指令,主要處理規則如下:
①將所有的#define刪除,並且展開所有的宏定義;
②處理所有條件編譯指令,如#if,#ifdef等;
③處理#include預編譯指令,將被包含的文件插入到該預編譯指令的位置。該過程遞歸進行,及被包含的文件可能還包含其他文件。
④刪除所有的注釋//和 /**/;
⑤添加行號和文件標識,如#2 “hello.c” 2,以便於編譯時編譯器產生調試用的行號信息及用於編譯時產生編譯錯誤或警告時能夠顯示行號信息;
⑥保留所有的#pragma編譯器指令,因為編譯器須要使用它們;
二、編譯(生成預編譯文件 ,.s文件)
gcc –S hello.i –o hello.s //可以不用指定名字,默認生成一個.s文件
編譯過程就是把預處理完的文件進行一系列詞法分析,語法分析,語義分析及優化后生成相應的匯編代碼文件。
三、匯編(生成匯編代碼,.o文件)
gcc –c hello.s –o hello.o //可以不指定,默認生成.o的文件
匯編器是將匯編代碼轉變成機器可以執行的命令,每一個匯編語句幾乎都對應一條機器指令。
四、鏈接(生成可執行文件)
gcc hello.o –o hello
鏈接器ld將各個目標文件組裝在一起,解決符號依賴,庫依賴關系,並生成可執行文件。
假定我們有一個程序名為hello.c的C語言源代碼文件,要生成一個可執行文件,最簡單的辦法就是∶
gcc hello.c -o myhello //一步即可完成
這時,預編譯、編譯連接一次完成,生成一個系統預設的名為myhello.out的可執行文件。