我們在控制檯打印hello過程究竟發生了什麼事,然我們一起目睹
你們知道我們最平時寫的最簡單的程序hello都幹了什麼了嗎下面讓我們一起來看一下
圖:編譯過程
程序:
#include <iostream>
using namespace std;
#define pi 3.14
int main()
{
//see helloword in screen
cout<<"helloword"<<endl;
cout<<"pi"<<pi<<endl;
return 0;
}
1、預編譯
我們首先連做下預編譯操作看看生成了什麼?
g++ -E hello.cpp -o hello.ii
這個小小的預編譯過程看我們預編譯生成的文件變成了這麼多行的一個文件,這個過程其實就是把#開始的預編譯命令#define #include等操作
a、將#define xx 將xx中的內容替換到我們預編譯文件中
b、條件預編譯指令#if #ifdef #ifndef #elseif # else #endif
c、#include 將我們要引入的文件直接粘貼在我們#include的地方
d、刪除註釋 // /**/
e、添加行號和文件標識符 #2 hello.cpp 用於調試時定位位置信息
f、保留#pragma指令
1、編譯
這部操作把預處理文件進行一系類的詞法分析語法分析語義分析級優化後產生相應的彙編代碼。
g++ -s hello.ii -o hello.s
這樣就可以生成hello.s彙編文件
上面操作:掃描 語法分析 語義分析 源代碼優化 代碼生成 目標代碼優化
a、詞法分析:理由難過一箇中類似有限狀態機將源代碼分割爲記號,放入符號表
b、語法分析:產生語法樹,(採用了上下文無關語法),通過語法樹分析語法錯誤比如括號不匹配等問題
c、語義分析:靜態語義、動態語義(識別了變量類型啊,賦值是否匹配啊,除數爲0啊都可以識別出來)
d、源碼級優化:一些初期可以優化的地方比如常量計算、比如a = 1 + 2 c = b +a 優化後就變爲c= b+3
e、目標代碼生成優化:選擇合適的尋址方式、使用移位來實現乘法計算,刪除多餘指令
1、彙編
這個過程是將剛纔我們生成的彙編代碼編譯爲機器可以執行的指令。
g++ -c hello.S -o hello.o
2、鏈接
鏈接過程不看不知道一看嚇一跳 怎麼這麼大一堆連接內容我 看着有點恐怖 後面慢慢分析
鏈接的個過程主要包括了地址和空間分配、符號決議和重定位(重定位:地址修正)(感覺最主要做的就是將函數信息地址等進行重定位,讓程序在運行的時候可以找到其它模塊中的函數活變量的地址)
ld -static /usr/lib/gcc/i386-redhat-linux/3.4.5/../../../crt1.o /usr/lib/gcc/i386-redhat-linux/3.4.5/../../../crti.o /usr/lib/gcc/i386-redhat-linux/3.4.5/crtbegin.o -L/usr/lib/gcc/i386-redhat-linux/3.4.5 -L/usr/lib/gcc/i386-redhat-linux/3.4.5 -L/usr/lib/gcc/i386-redhat-linux/3.4.5/../../.. /tmp/ccEoWbUY.o helloword.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/i386-redhat-linux/3.4.5/crtend.o /usr/lib/gcc/i386-redhat-linux/3.4.5/../../../crtn.o
3、我們來看看用g++ -c hello.cpp -o hello.o -v(編譯)和g++hello.cpp -o hello.o -v(生成可執行程序)執行過程中都幹了什麼可以很清晰看到