C語言_來了解一下GCC編譯器編譯C可執行指令碼的過程

OldBoy~發表於2017-12-27

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的可執行檔案。

相關文章