標籤:
一 前言
以前在編譯C++代碼的時候對編譯的錯誤都覺得很難理解,搞不清楚究竟是哪裡錯了。後來C++寫多了,總結了一些經驗,然後也瞭解了一下編譯過程,但是沒有系統的對編譯過程進行學習,現在趁著寫部落格的機會,好好的把編譯過程寫下來,並且理順一下這個知識點。
二 名詞解釋
編譯單元:當一個c或cpp檔案在編譯時間,前置處理器首先遞迴包含標頭檔,形成一個含有所有 必要資訊的單個源檔案,這個源檔案就是一個編譯單元。
目標檔案:目標檔案包含著機器代碼(可直接被電腦中央處理器執行)以及代碼在運行時使用的資料,此外還包括其他調試資訊。
三 編譯過程
在VC中編譯過程會分成以下三步:
1,預先處理
2,產生目標檔案
3,連結成可執行檔
1,預先處理
將標頭檔載入進來,處理各種#define,如:宏,先行編譯條件,產生一個獨立的編譯單元。
可以通過以下的命令來產生獨立的編譯單元。
cl /EP test.cpp > test_p.cpp
這個命令的意思是,把源檔案產生編譯單元並寫到test_p.cpp中。舉個例子
下面是源檔案代碼
// test.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <windows.h>#include <iostream>#define MAX(a,b) (a>b?a:b)#define PI 3.1415927#ifdef UNICODEtypedef wchar_t MTCHAR;#elsetypedef char MTCHAR;#endif // UNICODE
int _tmain(int argc, _TCHAR* argv[]){ std::cout << MAX(10, 20) << std::endl; std::cout << PI << std::endl; MTCHAR *str = _T("hello world!"); _tprintf(_T("%s\n"), str); return 0;}
原始碼中包含了三個標頭檔,定義一個運算式的宏,一個常量的宏,和使用先行編譯條件定義了一個字元類型
我們通過上面的命令產生新的檔案,包含檔案指令會把標頭檔引進來,把宏在代碼中替換掉,把先行編譯條件指令處理。
/*這裡省略掉大量的標頭檔代碼,整個檔案總共有三十多萬行。*/typedef char MTCHAR;int main(int argc, _TCHAR* argv[]){ std::cout << (10>20?10:20) << std::endl; std::cout << 3.1415927 << std::endl; MTCHAR *str = "hello world!"; printf("%s\n", str); return 0;}
也可以在cl命令中加入宏UNICODE和_UNICODE,這樣可以更清晰地看到預先處理條件指令的處理效果
cl /EP /D "UNICODE" /D "_UNICODE" test.cpp > test_p.cpp
產生的編譯單元
/*這裡省略掉大量的標頭檔代碼,整個檔案總共有三十多萬行。*/typedef wchar_t MTCHAR;int wmain(int argc, _TCHAR* argv[]){ std::cout << (10>20?10:20) << std::endl; std::cout << 3.1415927 << std::endl; MTCHAR *str = L"hello world!"; wprintf(L"%s\n", str); return 0;}
MTCHAR已經被定義為wchar_t而不是char了,而且字串也是wchar格式。
2,產生目標檔案
將編譯單元進行編譯,產生目標檔案(.obj檔案)。這裡通常分兩個階段:首先產生組合語言,然後適用彙編產生機器碼。
通過剛才產生的編譯單元來產生目標檔案
cl /c test_p.cpp
已經產生裡機器碼,所以不貼檔案內容了。
3,連結
連結的任務就是把目標檔案連起來產生可執行檔。
link test.obj
使用這個命令就能產生exe檔案。
4,cl命令
cl命令有幾個跟標準庫有關的選項:/ML,/MLd,/MT,/MTd,/MD,/MDd。這些選項是想告訴編譯器應用程式需要什麼標準庫。
/ML:(預設選項)對應單線程靜態標準庫。
/MT:對應多線程靜態標準庫 (libcmt.lib) ,此時編譯器會自動定義 _MT 宏。
/MD:對應多線程 DLL 版 ( 匯入庫 msvcrt.lib , DLL 是msvcrt.dll) ,編譯器自動定義 _MT 和 _DLL兩個宏。
/MLd:對應調試單線程靜態標準庫 (libcd.lib) 。
/MTd:對應調試多線程靜態標準庫 (libcmtd.lib) 。
/MDd:對應調試多線程 DLL 標準庫 ( 匯入庫msvcrtd.lib, DLL 是msvcrtd.dll) 。
VC++ 編譯過程