預編譯
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函數
進行相等判斷?爲什麼?
不可以,因爲內存對齊會影響到兩個大小形同,可能沒用的數據也進行了比較