天天看點

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...
前言

如果你使用內建環境開發。那麼你點選編譯按鈕就可生成可執行檔案。但是C程式從源代碼到二進制行程式都經曆了那些過程?你知道嗎?這些過程內建開發環境在點選編譯按鈕後都做完了,如果編譯沒有出錯,即可生成可執行檔案。本文将以Linux下C語言的編譯過程為例。對編譯過程進行讨論。

編譯一個C程式代碼

下面以Linux環境下的test.c為例,test.c裡的代碼為:

#include 
           

編譯輸出:

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

這個過程如此熟悉,以至于覺得編譯是一件很簡單的事。事實真的如此嗎?我們來細看一下C語言的編譯過程到底是怎樣的。

GCC編譯過程:
C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

圖檔來源于:GCC和Make編譯,連結和建構C/C ++應用程式

上述gcc指令其實依次執行了四步操作:

1.預處理(Preprocessing)

2.編譯(Compilation),

3.彙編(Assemble),

4.連結(Linking)。

預處理

以“#”号開頭的預處理指令如包含#include,宏定義制定#define等。在源程式中這些指令都放在函數之外,而且一般放在源檔案的前面。

使用預處理器把源檔案test.c經過預處理生成test.i檔案。

預處理的指令為:

gcc 
           

上述指令中-E是讓編譯器在預處理之後就退出,不進行後續編譯過程;-o是指定輸出檔案名。在本例中,預處理結果就是将stdio.h 檔案中的内容插入到test.c中了。

預處理生成的是test.i的文本檔案,這個文本檔案是可以直接通過cat指令進行文本檔案檢視的。

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

對比預處理、文本檔案、可執行檔案的大小

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

經過預處理之後代碼體積會大很多,相當于可執行檔案一倍大小。預處理之後的程式還是文本,可以用文本編輯器打開。

編譯

這裡的編譯不是指程式從源檔案到二進制程式的全部過程,而是指将經過預處理檔案(test.i)之後的程式轉換成特定彙編(test.s)代碼的過程。

編譯的指令為:

gcc 
           

上述指令中-S讓編譯器在編譯之後停止,不進行後續過程;-o是指定輸出檔案名。編譯過程完成後,将生成程式的彙編代碼test.s,這也是文本檔案。

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

檢視彙編代碼和代碼大小:

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

編譯成彙編檔案大小已經非常小了,沒有像預處理的時候檔案大小這麼臃腫。

cat test.s

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

裡面彙編是什麼意思,就不要問我了。哈哈~

彙編

彙編過程将上一步的彙編代碼轉換成機器碼,這一步産生的檔案叫做目标檔案,是二進制格式。

編譯的指令為:

gcc 
           
C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...

部分内容截圖如下:

C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...
連結

連結過程使用連結器将該目标檔案與其他目标檔案、庫檔案、啟動檔案等連結起來生成可執行檔案。附加的目标檔案包括靜态連接配接庫和動态連接配接庫。

連結過程的指令為:

gcc 
           
C++報錯無效的預處理指令include_GCC編譯過程(預處理->編譯->彙編->連結)...
總結

生成可執行程式過程為成四個步驟:

1、由.c檔案到.i檔案,這個過程叫預處理。

2、由.i檔案到.s檔案,這個過程叫編譯。

3、由.s檔案到.o檔案,這個過程叫彙編。

4、由.o檔案到可執行檔案,這個過程叫連結。

歡迎關注微信公衆号“

程式猿編碼

” ,這裡Linux c/c++ 、Python、Go語言、資料結構與算法、網絡程式設計相關知識,常用的程式員工具。每日00:10之前更新新聞簡報,一份簡報,縱覽天下事!