預處理指令,就是我們常說的宏定義。在編譯器對 C或者 objective-c 進行編譯前,編譯器會對這些預處理命令進行處理,在編譯源程序時,會將定義的內容進行替換編譯。
正確地使用預處理可以簡化代碼、提高代碼的可讀性和編寫效率。
使用#define及#undef 執行宏定義
這里#define的作用是為后面的語句起一個別稱,可以使用有意義的名字代替,可以簡化編寫過程,提高程序可讀性。例:
//將一些常量值定義成有意義的名稱,可以提高程序可讀性
//實際項目開發中,常把一些未來可能需要修改的值定義成宏,這樣可以避免批量更改代碼中的值
#define PI 3.14159
//將獲取屏幕寬度的代碼定義成宏,可以簡化代碼,提升編寫效率
#define KScreenWidth ([[UIScreen mainScreen] bounds].size.width)
需要注意的是
宏定義不是C 語句。無需用分號結束,也不要使用=進行賦值。
宏定義不是變量。不要對宏名稱進行賦值。
編譯器處理宏定義,只是進行”查找,替換”,要保證宏定義是正確的。
執行宏定義后,該宏的作用 域為定義該宏開始,直到該源代碼結束,如果想提前結束宏定義,可以使用語句:#undef 宏名稱
帶參數的宏定義
可以在宏定義中使用參數,這樣定義的宏更靈活。 格式為:
#define 宏名稱(參數列表) 字符串
例如,將UIColor的創建進行紅定義,可以大大簡化設置顏色的過程:
//RGB色值
#define RGB(r,g,b) [UIColor colorWithRed:r/255. green:g/255. blue:b/255. alpha:1.]
#define RGBA(r,g,b,a) [UIColor colorWithRed:r/255. green:g/255. blue:b/255. alpha:a]
//十六進制顏色
#define HEXCOLOR(str) [UIColor hexFloatColor:str]
需要注意的是
因為宏定義只是執行簡單查找和替換,當傳入的參數是個表達式的時候,常會出現一些我們不希望出現的錯誤。所以,為了編譯器能正確處理宏定義,建議將宏定義中的參數用圓括號括起來。如果整個宏定義返回的是數值,可再將整個宏定義的字符串用圓括號括起來。
使用#ifdef,#ifndef,#else,#endif 執行條件編譯
有時候需要選擇性編譯——比如對于特定的設備,只編譯該設備相關的代碼,就可以借助條件編譯來完成。
語法格式1:
//已定義某個宏,則執行
#ifdef 宏名稱
//任意語句
#endif
//如果未定義某個宏,則執行
#ifndef 宏名稱
//任意語句
#endif
根據是否定義了指定的宏,選擇執行
語法格式2:
//已定義某個宏
#ifdef 宏名稱
//任意語句
#else
//任意語句
#endif
//如果未定義某個宏
#ifndef 宏名稱
//任意語句
#else
//任意語句
#endif
其使用過程類比平常代碼中使用的if...else...
通過條件編譯語句,可以較方便地自適應不同的設備。
通過判斷是否debug模式來輸出,例:
//DEBUG 模式下打印日志,當前行
#ifdef DEBUG
#define GZCLog(fmt,...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__);
#define GZCPrint(...) printf(__VA_ARGS__)
#else
#define GZCLog(...)
#define GZCPrint(...)
#endif
使用#if,#elif,#else,#endif 進行條件編譯
對表達式進行判斷,根據表達式的值決定是否要編譯指定的語句。
語法格式:
#if 表達式
//任意語句
#elif 表達式
...// 可以有零到多個#elif 語句
#else
//任意語句
#endif
條件編譯語句和流程控制語句有何區別?
使用條件編譯指令時,不符合條件的程序語句根本不會編譯;
使用普通的分支語句時,所有的代碼都被編譯成執行性代碼,程序運行時再根據需要決定執行哪些語句。
這就意味著條件編譯語句生成的文件更小,執行效率更高。
#include 與#import
和C語言相同,#include 指令的作用很簡單:將指定的源碼插入到當前代碼的制定位置。但有個顯著的缺點,需要程序員自行判斷是否重復導入。但#import可以幫助判斷,避免重復導入的問題。
OC中,#import 中引號和尖括號的作用:
雙引號,告訴預處理程序到當前文件所在路徑搜索指定的源文件(也可通過 Xcode 的項目設置來設置預處理的搜索路徑);
而尖括號<>,告訴預處理程序到相應的系統頭文件路徑中搜索。