天天看點

《gcc五分鐘系列》第九節:編譯過程

《gcc五分鐘系列》第九節:編譯過程

    接下來幾節,我會講一些編譯期相關的優化選項及預編譯期相關的優化選項。至于彙編期和連結期……我就完全不懂了。我不懂彙編語言。連結期也涉及了很多我完全不懂的問題。

    那麼,編譯期是什麼意思?預編譯期又是什麼意思?這個涉及到編譯的整個過程。我記得前面某節好像提到過這個話題,這裡詳細的講一下。

    從源代碼(xxx.cpp)生成可執行檔案(a.out)一共分為四個階段:

    1、預編譯階段:

    此時編譯器會處理源代碼中所有的預編譯指令。預編譯指定非常有特點,全部以“#”開頭。

    想想,以“#”開頭的指令有哪些?

    不同的指令有不同的處理方法,#include指令的處理方法就是赤裸裸的複制粘貼。将#include後面的檔案的内容赤裸裸地複制粘貼到#include指令所在的位置。#define指令分為帶參宏和不帶參宏。#define指令的處理方法,學名叫宏展開。其實不帶參宏的處理方法就是赤裸裸的字元串替換。之後會産生一篇完全不包含預編譯指令的代碼。

    使用gcc的-e選項可以檢視預編譯結果:

    g++ -e xxx.cpp

    但是這個指令不會把處理結果儲存在檔案中,而是放在标準輸出中。

    例子:見本文最後例一。

    2、彙編階段:

    此時編譯器會将預處理過的代碼進行彙編。

    使用gcc的-s選項可以檢視彙編結果:

    g++ -s xxx.cpp

    之後會在目前目錄下産生一個xxx.s的檔案,裡面儲存的是彙編代碼。

    彙編我不懂,就不帖了。

    3、編譯階段:

    此時編譯器會将彙編代碼編譯成目标檔案。

    使用gcc的-c選項可以生成目标檔案:

    g++ -c xxx.s

    也可以從源代碼直接生成目标檔案:

    g++ -c xxx.cpp

    gcc會通過擴充名自動判斷處理的是彙編代碼還是c++代碼。

    到此,編譯器已經完成它的全部工作。

    4、連結階段:

    此時已經沒有編譯器的事情了。連結工作交由連結器來處理。連結器會将多個目标檔案連結成可執行檔案。

    我們可以通過gcc來進行連結,但是實際上,gcc還是調用ld指令來完成連結工作的。

    g++ xx1.o xx2.o

    本節完。

    計劃先講編譯階段的pipe選項、o選項和w選項。因為編譯階段事情比較少。

    然後講預編譯階段的i選項和d選項。

例一: