寫在前面
????對于C語言,我們大家可能不陌生。工作中經(jīng)常會使用到,我們在工作中寫代碼,其中的編譯和執(zhí)行過程都是交給IDE來運行的,其中C語言從源文件(.c)文件到最后的執(zhí)行結(jié)果,其中到底經(jīng)過了那幾步,卻鮮為人知。
????最近正好在復習C語言,希望可以拋磚引玉,不足之處,請大家留言,大神請飄過。
首先,第一部分向大家簡單展示一下C語言的編譯過程,第二部分,我們再通過具體的代碼示例向大家展示。
第一部分
C語言編譯過程簡述
??C語言的編譯過程有以下幾個步驟,分別是:
- 預處理:??gcc -E Hello.c -o Hello.i
- 匯編:??gcc -S Hello.i -o Hello.s
- 編譯為二進制:??gcc -c Hello.s -o Hello.o ????// -c 中的c是小寫
- 鏈接:??gcc Hello.o -o Hello
?.c 結(jié)尾的是C語言文件
?.i 結(jié)尾的是處理后的C語言文件
?.s 結(jié)尾的是編譯后的匯編文件
?.o 是編譯后的目標文件
第二部分
具體示例
第一步,編輯Hello.c源文件
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf("Hello World!\n");
return 0;
}
第二步,執(zhí)行預處理
預處理過程實質(zhì)上是處理“#”,將#include包含的頭文件直接拷貝到Hello.c當中;將#define定義的宏進行替換,同時將代碼中沒用的注釋部分刪除等...
具體做的事兒如下:
(1)將所有的#define刪除,并且展開所有的宏定義,其實就是字符替換;
(2)處理所有的條件編譯指令,#ifdef #ifndef #endif等,就是帶#的那些;
(3)處理#include,將#include指向的文件插入到該行處;
(4)刪除所有注釋;
(5)添加行號和文件標示,在調(diào)試和編譯出錯的時候才知道錯誤位置;
(6)保留#pragma編譯器指令,因為編譯器需要使用它們。
執(zhí)行:gcc -E Hello -o Hello.i
預處理的結(jié)果
第三步,執(zhí)行匯編
編譯的過程實質(zhì)上是把高級語言翻譯成機器語言的過程,即對Hello.c做了這些事兒
(1)詞法分析;
(2)語法分析;
(3)語義分析;
(4)優(yōu)化后生成相應的匯編代碼。
執(zhí)行:gcc -S Hello.i -o Hello.s
編譯后的結(jié)果
第四步,翻譯為二進制代碼
執(zhí)行:gcc -c Hello.s -o Hello.o
編譯后結(jié)果
第五步,鏈接處理
可以生成可執(zhí)行程序,就像剛才的hello.c它使用到了C標準庫的東西“printf”,但是編譯過程只是把源文件翻譯成二進制而已,這個二進制還不能直接執(zhí)行,這個時候就需要做一個動作,將翻譯成的二進制與需要用到庫綁定在一塊。
執(zhí)行:gcc Hello.o -o Hello
鏈接后結(jié)果