1. 程式人生 > >Linux之GCC命令 -- 解析GCC編譯的四個過程

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在編譯時預設使用動態庫。