NDK開發彙總
一 預處理指令
C 語言執行的流程:
- 組成程式的每個源檔案通過編譯過程分别轉換成目标代碼(object code)
- 各目标檔案由連接配接器 捆綁在一起,形成一個單一而完整的可執行檔案
預處理器不是編譯器,但是它是編譯過程中一個單獨的步驟。
預處理器是一個文本替換工具
所有的預處理器指令都是以井号(#)開頭
而編譯過程又由如下過程組成:
- 預處理器處理,在這個階段,預處理器在源代碼上執行一些文本操作。例如:用實際值代替由 #define指令定義的符号以及讀入由#include指令包含的檔案的内容。
- 源代碼經過解析,判斷它的語句的意思,這個階段會産生絕大多數錯誤和警告資訊的地方,随後便生成目标代碼。
執行階段:
- 程式必須載入到記憶體中。
- 程式執行
- 程式執行的最後一個階段就是程式終止。
二 常用預處理器
預處理器 | 說明 |
---|---|
#include | 導入頭檔案 |
#if | if |
#elif | else if |
#else | else |
#endif | 結束 if |
#define | 宏定義 |
#ifdef | 如果定義了宏 |
#ifndef | 如果未定義宏 |
#undef | 取消宏定義 |
三Define指令
1 無參宏定義
#define 辨別符 字元串
定義常量
意義: 就是宏替換的作用,讓 辨別符替換 字元串,這隻是一種簡單的文本替換,預處理程式對它不作任何檢查。如有錯誤,隻能在編譯已被宏展開後的源程式時發現。
反例
#define pint(int*)
pint pa, pb;
本意是定義pa和pb均為int型指針,但實際上變成int* pa,pb;。pa是int型指針,而pb是int型變量。本例中可用typedef來代替define,這樣pa和pb就都是int型指針了。因為宏定義隻是簡單的字元串代換,在預處理階段完成,而typedef是在編譯時處理的,它不是作簡單的代換,而是對類型說明符重新命名,被命名的辨別符具有類型定義說明的功能
無參宏注意事項:
- 宏名一般用大寫字母表示,以便于與變量差別。
- 宏定義末尾不必加分号,否則連分号一并替換。
- 宏定義可以嵌套。
- 可用#undef指令終止宏定義的作用域。
- 使用宏可提高程式通用性和易讀性,減少不一緻性,減少輸入錯誤和便于修改。如數組大小常用宏定義。
- 預處理是在編譯之前的處理,而編譯工作的任務之一就是文法檢查,預處理不做文法檢查。
- 宏定義寫在函數的花括号外邊,作用域為其後的程式,通常在檔案的最開頭。
-
字元串" "中永遠不包含宏,否則該宏名當字元串處理。
宏定義不配置設定記憶體,變量定義配置設定記憶體
2 帶參宏定義
#define宏名(參數) 字元串
例如:
#define INC(x) x+1
y = INC(5);
反例:
#define SQ(r ) rr
Y = SQ(a+b); 結果= a+ba+b;
使用案例:
我們最常用的一種替代方案區最大最小值:
#define MAX(x,y) (((x) > (y)) ? (x): (y))
#define MAX(x, y) ((x) > (y)) ? x: y
#define M
int main() {
#include "A.txt"
for (int i = 0; i < 5; i++)
{
printf("%d \n", i);
}
int max = MAX(3, 5);
printf("%d \n", max);
#ifdef N
#ifdef M
printf("%d \n", 110);
#else
printf("%d \n", 120);
#endif
#endif
#ifndef X
printf("%d \n", 130);
#endif
system("pause");
return 0;
}
- #define 辨別符 字元串 ,編譯時字元串會替代辨別符
- #define 的字元串如果後面帶; ,則;會被帶到需要替換辨別符的地方
- 有ifndef 後面就要跟着 #endif ,可以了解為如果#define 了某個标記,則将執行…
三 檔案包含
檔案包含指令把指定頭檔案插入該指令行位置取代該指令行,進而把指定的檔案和目前的源程式檔案連成一個源檔案。
在程式設計中,檔案包含是很有用的。一個大程式可以分為多個子產品,由多個程式員分别程式設計。有些公用的符号常量或宏定義等可單獨組成一個檔案,在其它檔案的開頭用包含指令包含該檔案即可使用。這樣,可避免在每個檔案開頭都去書寫那些公用量,進而節省時間,并減少出錯。
#include <> 或者 #include “” 差別
< > 和 “ ” 差別在于: 使用《》 表示在包含檔案目錄中去查找 (包含目錄是由使用者在設定環境時設定的include 目錄“解決方案管理器 -> 屬性-> 配置屬性 -> VC++ 目錄”),而不是在目前源檔案目錄去尋找; 使用雙引号就是先從目前源檔案目錄中查找。
四 條件編譯
第一種方式
#ifdef 辨別符 (或者#if defined)
程式段1
#else
程式段2
#endif
或者
#ifdef 辨別符 (或 #if defined 辨別符)
程式段
#endif
第二種方式
#ifndef
#else
#endif
第三種方式
#if
#else
#endif
在實踐中的作用:
-
屏蔽跨平台差異
在大規模開發過程中,特别是跨平台和系統的軟體裡,可以在編譯時通過條件編譯設定編譯環境。
#ifdef WINDOWS
#define MYTYPE long
#else
#define MYTYPE float
#endif
- 包含程式功能子產品
#ifdef FLV
Include “fastleavec”
#endif
當不許向别的使用者提供該功能,則在編譯之前将首部的FLV 加一下橫線即可
- 開關調試資訊
#ifdef DEBUG
Prinft(“device_open (%d)\n”, file);
#endif
這個DEBUG 就是一個開關。可以在整個工程的一個公用的頭檔案中,當我們處于debug 階段的時候就将這個開關打開,當我們程式release 版本裡面的時候就将這個開關關閉。
-
避開硬體的限制
有時一些具體的應用環境的硬體不同,但限于條件本地缺乏這種裝置,可繞過硬體直接寫出預期結果:
#ifndef TEST
I = dial();
#else
I = 0;
#endif
-
防止頭檔案重複包含
頭檔案可以被頭檔案或者C檔案包含。由于頭檔案包含可以嵌套,C檔案就有可能多次包含同一個檔案; 或者不同的C檔案都包含同一個頭檔案,編譯時就可能出現重複包含的問題。
#ifndef HEAD_A
#define HEAD_A
#include <>
#endif