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