你們知道計算機使用的一系列的1和0ios
那個一個C++語言程序又是如何從一個個.h和.cpp文件變成包含1和0的可執行文件呢?c++
能夠認爲有如下的幾個環節編程
源程序->預處理->編譯和優化->生成目標文件->連接->可執行文件windows
1.預處理函數
C++的預處理是指在C++程序源代碼被編譯以前,由預處理器對C++程序源代碼進行的處理。這個過程並不對程序的源代碼進行解析。優化
這裏的預處理器(preprocessor)是指真正的編譯開始以前由編譯器調用的一個獨立程序。this
預處理器主要負責如下的幾處spa
1.宏的替換.net
2.刪除註釋翻譯
3.處理預處理指令,如#include,#ifdef
如咱們有如下代碼
temp.h
#ifndef _HEADERNAME_H #define _HEADERNAME_H 1 #include <iostream> inline void show(char *a) { std::cout << a<< std::endl;//annotation } #endif
main.cpp
#include "temp.h" #define MACRO "This is a macro" extern int i; int main() { std::cout<<i<<std::endl; show(MACRO); }
a.cpp
#include <iostream> int i=100;
*在vs2013中可使用「VS2013 開發人員命令提示」
使用cl /P main.cpp只進行預編譯生成main.i文件
*g++中可使用(在如下只使用g++進行演示)
g++ –E main.cpp>main.i命令
g++ –E a.cpp>main.i
打開生成的A.i文件
咱們發現
一、show函數中的註釋已經被刪掉了
二、main函數中的MACRO宏被替成了"this is a macro」
windows vs下
三、temp.h和main.cpp中的#include<iostream> 和#include 「temp.h」也在相應位置被展開了
2.編譯和優化
詞法分析 -- 識別單詞,確認詞類;好比int i;知道int是一個類型,i是一個關鍵字以及判斷i的名字是否合法
語法分析 -- 識別短語和句型的語法屬性;
語義分析 -- 確認單詞、短語和句型的語義特徵;
代碼優化 -- 修辭、文本編輯;
代碼生成 -- 生成譯文。
內聯函數的替換就發生在這一階段
在g++中可使用
g++ -S將預處理階段生成的.i文件生成相應的彙編文件
g++ –S main.i main.s
g++ –S a.i a.s
生成的部分代碼以下:
3.生成目標文件
彙編過程實際上指把彙編語言代碼翻譯成目標機器指令的過程。
在最終的目標文件中
除了擁有本身的數據和二進制代碼以外,還要至少提供2個表:未解決符號表和導出符號表,分別告訴連接器本身須要什麼和可以提供什麼。
編譯器把一個cpp編譯爲目標文件的時候,除了要在目標文件裏寫入cpp裏包含的數據和代碼,還要至少提供3個表:未解決符號表,導出符號表和地址重定向表。
未解決符號表提供了全部在該編譯單元裏引用可是定義並不在本編譯單元裏的符號及其出現的地址。
導出符號表提供了本編譯單元具備定義,而且願意提供給其餘編譯單元使用的符號及其地址。
地址重定向表提供了本編譯單元全部對自身地址的引用的記錄。
g++中可使用g++ -c命令
g++ –c main.s –o main.o
g++ –c a.s –o a.o
4.連接
由彙編程序生成的目標文件並不能當即就被執行,其中可能還有許多沒有解決的問題。例如,某個源文件中的函數可能引用了另外一個源文件中定義的某個符號(如變量或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。全部的這些問題,都須要經連接程序的處理方能得以解決。
g++ a.o main.o –o main.out
最終運行結果以下
100
This is a macro
參考文獻
C/C++程序從編譯到最終生成可執行文件的過程分析 http://blog.csdn.net/wyb19890515/article/details/7211006
c/c++程序編譯鏈接過程 http://blog.csdn.net/hitprince/article/details/7880241