天天看點

Linux之GCC指令 -- 解析GCC編譯的四個過程

在Linux下進行C語言程式設計,必然要采用GNU GCC來編譯C源代碼生成可執行程式。Gcc指令的一般格式為:

Gcc [選項] 要編譯的檔案 [選項] [目标檔案]。其中,目标檔案可預設,Gcc預設生成可執行的檔案名為:編譯檔案.out

看一下經典入門程式"Hello World!"

# vi hello.c ,編輯如下:

#include <stdlib.h>

#include <stdio.h>

void main(void)

{

       printf("hello world!/r/n");

}

用gcc編譯成執行程式。#gcc hello.c,該指令将hello.c直接生成最終二進制可執行程式a.out。./a.out就可以執行。注意:必須有main主函數。

      這條指令隐含執行了(1)預處理、(2)彙編、(3)編譯、(4)連結,形成最終的二進制可執行程式。現在我們就用GCC的指令選項來逐個剖析GCC過程。

1)預處理(Pre-processing)。在該階段,編譯器将C源代碼中的包含的頭檔案如stdio.h編譯進來,使用者可以使用gcc的選項”-E”進行檢視。用法:#gcc -E hello.c -o hello.i,作用:将hello.c預處理輸出hello.i檔案(-o選項指定特定的目标檔案名,如gcc -o client.exe client.c)。通過vi hello.i可以看到預處理過程資訊。

2)編譯階段(Compiling)。在這個階段中,Gcc首先要檢查代碼的規範性、是否有文法錯誤等,以确定代碼的實際要做的工作,在檢查無誤後,Gcc把代碼翻譯成彙編語言。使用者可以使用”-S”選項來進行檢視,生成彙編代碼。

用法:[root]# gcc –S hello.i –o hello.s

3)彙編階段(Assembling)。彙編階段是把編譯階段生成的”.s”檔案轉成二進制目标代碼。用法:[root]# gcc –c hello.s –o hello.o

4)連結階段(Link)。用法:[root]# gcc hello.o –o hello.exe,作用:将編譯輸出檔案hello.o連結成最終可執行檔案hello.exe。

      在這個程式中并沒有定義”printf”的函數實作,且在預編譯中包含進的”stdio.h”中也隻有該函數的聲明,而沒有定義函數的實作,那麼,是在哪裡實作”printf”函數的呢?最後的答案是:系統把這些函數實作都被做到名為libc.so.6的庫檔案中去了。可以用ldd指令檢視動态庫加載情況:[root]# ldd hello.exe。

       函數庫一般分為靜态庫和動态庫兩種。靜态庫是指編譯連結時,把庫檔案的代碼全部加入到可執行檔案中,是以生成的檔案比較大,但在運作時也就不再需要庫檔案了。其字尾名一般為“.a”。動态庫與之相反,在編譯連結時并沒有把庫檔案的代碼加入到可執行檔案中,而是在程式執行時由運作時連結檔案加載庫,這樣可以節省系統的開銷。動态庫一般字尾名為”.so”,如前面所述的libc.so.6就是動态庫。gcc在編譯時預設使用動态庫。

本文來自CSDN部落格,轉載自:http://blog.csdn.net/zhandoushi1982/archive/2009/11/29/4902136.aspx

                          karen

繼續閱讀