編譯器是由幾部分組成的,包括預處理器,編譯器,彙編器,連結器。
我們寫的代碼經過預處理器,變成 .i 檔案,再經過編譯器處理,變成 .s 檔案,再經彙編器,生成 .o 檔案,最後經連結器,變成可執行檔案。
預處理器,編譯器,彙編器,連結器都做了什麼呢,我們接着看
處理所有的注釋,以空格代替
将所有的 #define 删除,并且展開所有的宏定義
處理條件編譯指令 #if,#ifdef,#elif,#else,#endif
處理 #include,展開被包含的檔案
保留編譯器需要使用的 #pragma
預處理指令執行個體:gcc -e file.c -o file.i
gcc -e 19-1.c -o 19-1.i
得檔案 19-1.i 檔案,下面是 19-1.i 檔案
可以看到,注釋被直接去除,頭檔案被直接展開,宏定義被直接展開。以 # 開頭的資訊是給後續編譯器其他子產品使用的。
對預處理檔案進行詞法分析,文法分析和語義分析
詞法分析:分析關鍵字,标示符,立即數等是否合法
文法分析:分析表達式是否遵循文法規則
語義分析:在文法分析的基礎上進一步分析表達式是否合法
分析結束後進行代碼優化生成相應的彙編代碼檔案
編譯指令執行個體:gcc -s file.i -o file.s
gcc -s 19-1.i -o 19-1.s
生成 19-1.s 如下,裡面的彙編代碼這裡不做解析了。
彙編器将彙編代碼轉變為機器的可以執行執行
每條彙編語句幾乎都有對應一條機器指令
彙編指令示例:gcc -c file.s -o file.o
gcc -c 19-1.s -o 19-1.o
生成檔案19-1.o,這裡還不是可執行檔案。
經過連結器處理才能生成可執行檔案:gcc 19-1.o -o 19-1
編譯過程分為預處理,編譯,彙編和連結四個階段
1、預處理:處理注釋,宏以及以 # 開頭的符号
2、編譯:進行詞法分析,文法分析和語義分析等
3、彙編:将彙編代碼翻譯成機器指令的目标檔案