1、預處理編程
預處理指令的執行主要包含下列事情:函數
1.頭文件的包含優化
2.註釋的刪除操作系統
3.宏定義的替換翻譯
4.條件編譯的選擇編譯器
指令:gcc -E test.c -o test.i it
/* 調用的是預處理器cpp, -E:只進行預處理操做,-o:輸出到<文件> , .i表示產生的臨時文件 Intermediate */編譯
2、編譯table
編譯以前,C語言編譯器會進行詞法分析、語法分析(-fsyntax-only)。test
在確認全部的指令都符合語法規則以後,將其翻譯成相應的後綴爲S的彙編文件。
指令:gcc -S test.i -o test.S
/* 調用的是編譯器ccl, -S:編譯到彙編語言,不進行彙編和連接, .S:表示彙編文件,注意於.s彙編文件的區別 */
.s :彙編語言源程序;彙編
.S:彙編語言源程序;預處理,彙編
小寫的s文件,在後期階段不在進行預處理操做,因此咱們不能在這裏面寫預處理的語句在裏面
大寫的S文件,還會進行預處理、彙編等操做,因此咱們能夠在這裏面加入預處理的命
3、彙編
在編譯與彙編之間,編譯器一般還會作一些優化操做。
彙編過程實際上指把彙編語言代碼翻譯成目標機器指令的過程
指令:gcc -c test.S -o test.o
/* 調用的是彙編器as,-c:編譯、彙編到目標代碼,不進行連接, .o表示產生目標文件, object
此時用file查看test.o文件的類型爲ELF 32-bit LSB relocatable類型,這是可重定位的格式 */
4、連接
由彙編程序生成的目標文件並不能當即就被執行,其中可能還有許多沒有解決的問題。例如,某個源文件中的函數可能引用了另外一個 源文件中定義的某個符號(如變量或者函數調用等);在程序中可能調用了某個庫文件中的函數等等。全部的這些問題,都須要經連接程序的處理方能得以解決。
連接程序的主要工做就是將有關的目標文件彼此相鏈接,也即將在一個文件中引用的符號同該符號在另一個文件中的定義鏈接起來,使得全部的這些目標文件成爲一個可以誒操做系統裝入執行的統一總體。
函數庫通常分爲靜態庫和動態庫兩種。靜態庫是指編譯連接時,把庫文件的代碼所有加入到可執行文件中,所以生成的文件比較大,但在運行時也就再也不須要庫文件了。其後綴名通常爲」.a」。動態庫與之相反,在編譯連接時並無把庫文件的代碼加入到可執行文件中,而是在程序執行時由運行時連接文件加載庫,這樣能夠節省系統的開銷。動態庫通常後綴名爲」.so」,如前面所述的libc.so.6就是動態庫。gcc在編譯時默認使用動態庫。
指令:gcc test.o -o test
/* 用file查看test文件類型爲:ELF 32-bit LSB executable,這是能夠被執行的文件格式 */