咱們大部分程序員可能都是從C語言學起的,寫過幾萬行、幾十萬行、甚至上百萬行的代碼,可是你們是否都清楚C語言編譯的完整過程呢,若是不清楚的話,我今天就帶着你們一塊兒來作個解密吧。程序員
C語言相對於彙編語言是一種高級語言,要想在系統上運行,須要經過編譯器把它轉換成機器可以讀懂的可執行的代碼。函數
以Linux系統上的gcc爲例,一般咱們編譯一個源文件都是用下面的命令:學習
$gcc hello.c –o hello
編譯成功後,目錄裏會生成hello這個程序,直接運行它能夠看到結果。操作系統
$./hello3d
Hello World!blog
但hello這個程序是怎麼生成的呢,其實中間仍是有好幾步的。用下面這個命令從新編譯一下,你能夠看到全部的中間文件。編譯器
$gcc -save-temps hello.c –o helloio
$ls編譯
hello hello.c hello.i hello.o hello.sclass
C編譯器的編譯過程主要分紅四步:
(1) 預處理
(2) 編譯
(3) 彙編
(4) 鏈接
1) 預處理 Pre-prosssing
預處理生成了hello.i 的中間文件,主要完成了下面幾步:
去掉全部的註釋
展開全部的宏定義(也就是作字符替換)
插入#include文件的內容
處理全部的條件編譯
hello.i 文件內容以下(文件較大,只展現了最下面的一塊):
能夠發現源代碼中全部的註釋被刪除了,而且插入了stdio.h頭文件的內容。
2)編譯 Compiling
編譯將 hello.i 文件編譯生成一箇中間文件 hello.s,打開能夠看到裏邊都是彙編語言,因此編譯的做用就是把源代碼轉換成彙編語言。
3)彙編 Assembly
彙編器將 hello.s 彙編成 hello.o 文件。hello.o是二進制文件,裏邊都是機器能夠執行的代碼。
4)鏈接 Linking
鏈接顧名思義起到了一個鏈接做用,雖然 hello.o 已是二進制文件了,可是裏邊用到的好比 printf 函數須要調用別的庫。鏈接器將咱們的二進制文件和其餘庫作了一個綁定。能夠看到鏈接後生成的 hello 文件要比 hello.o 大的多。
到這裏 C的完整編譯流程就結束了,本文的示例用的是Linux操做系統,編譯器用的是 gcc,但在其餘操做系統,好比 Unix、Windows,或者用其餘編譯器,原理都是同樣的,感興趣的同窗能夠去學習一下編譯原理,會對編譯有更深刻的理解。