預編譯
1、處理所有的注釋,以空格代替
2、将所有的#define删除,并且展開所有的宏定義
3、處理條件編譯指令#if,#ifdef,#elif,#else,#endif
4、處理#include,展開被包含的檔案
5、保留編譯器需要使用的#pragma指令
編譯
1、對預處理檔案進行一系列詞法分析,文法分析和語義分析
2、詞法分析主要分析關鍵字,标示符,立即數等是否合法
3、文法分析主要分析表達式是否遵循文法規則
4、語義分析在文法分析的基礎上進一步分析表達式是否合法
5、分析結束後進行代碼優化生成相應的彙編代碼檔案
彙編
1、彙編器将彙編代碼轉變為機器可以執行的指令
2、每個彙編語句幾乎都對應一條機器指令
連結器的作用
1、連接配接器的主要作用是把各個子產品之間互相引用的部分
2、處理好,使得各個子產品之間能夠正确的銜接。
編譯器将編譯工作主要分為預處理,編譯和彙編三部
1、連接配接器的工作是把各個獨立的子產品連結為可執行程式
2、靜态連結在編譯期完成,動态連結在運作期完成
#define
1、#define表達式給有函數調用的假象,卻不是函數
2、#define表達式可以比函數更強大
3、#define表達式比函數更容易出錯
4、最好不要定義時間點的量,如i++,
5、#definept允許這樣定義,但沒有仍和意義,将pt的内容替換為空,或者說,是直接删去
6、define可以替代任何變量,這個操作隻是預編譯中,替換而已
7、define的功能比函數強大,但是漏洞比函數大的多。
定義的内置宏,用于實作發現那個行出錯的消息。
__line__目前行
__file____date__目前的時間和檔案名
。。。
條件編譯
1、條件編譯的行為類似于c語言中的if…else
2、條件編譯是預編譯訓示指令,用于控制是否編譯某段代碼
即在預編譯時去除掉一些代碼,選擇性的進行編譯
#include的困惑
1、#include的本質是将已經存在的檔案内容嵌入到目前檔案中
2、#include的間接包含同樣會産生嵌入檔案内容的動作
如果間接的包含相同的頭檔案怎麼辦?會不會出錯?
會出錯,但是處理的方式是ifndef_headname_h_
條件編譯的意義:
1、條件編譯使得我們可以按不同的條件編譯不同的代碼段,
因而可以産生不同的目标代碼
2、#if…#else…#endif被預編譯器處理;而if…else語句被
編譯器處理,必然被編譯進目标代碼
3、實際工程中條件編譯主要用于一下兩種情況:
不同的生産線共用一份代碼
區分編譯産品的調試版和釋出版
通過編譯器指令行能夠定義預處理器使用的宏
條件編譯可以避免重複包含頭同一個頭檔案
條件編譯是在工程開發中可以差別不同産品線的代碼
條件編譯可以定義産品的釋出版和調試版
#error用于生成一個編譯錯誤消息,并停止編譯
用法
#errormessage
注:message不需要用雙引号包圍
#error編譯訓示字用于自定義程式員特有的編譯錯誤消息
類似的,
#warning用于生成編譯警告,但不會停止編譯
#line用于強制指定新的行号和編譯檔案名,并對源程式
的代碼重新編号
#linenumberfilename
注:filename可省略
#line編譯訓示字的本質是重定義__line__和__file__
用途:無關表示部分的代碼有某個人開發的,開發的那個程式段出現錯誤,
也就是告訴調試者的寫的代碼的相對位置進行檢錯。
現在有個更好的處理技術,來處理這個問題的。
#pragma簡介
1、#pragma是編譯器訓示字,用于訓示編譯器完成一些特定的動作
2、#pragma所定義的很多訓示字是編譯器和作業系統特有的
3、#pragma在不同的編譯器間是不可移植的
4、預處理器将忽略它不認識的#pragma指令
5、兩個不同的編譯器可能以兩種不同的方式解釋同一條#pragma指令
6、确定程式設計的的版本,便于差錯,用于顯示自己的程式的版本
提示作者版本是否正确
#pragmamessage("compileandroidsdk2.0...")
深入:
1、預處理器将忽略它不認識的#pragma指令
2、兩個不同的編譯器可能以兩種不同的方式解釋同一條#pragma指令
一般用法:
#pragmaparameter
注:不同的parameter參數文法和意義各不相同
#pragma的記憶體對齊
構體變量是否可以直接用memcmp函數
進行相等判斷?為什麼?
不可以,因為記憶體對齊會影響到兩個大小形同,可能沒用的資料也進行了比較