在 C 語言中,預處理代碼 (PReprocessor) 是非常強大的工具,能讓你的代碼變得更加易讀和易改。利用預處理代碼,你可以重新定義代碼的一部分,使得你的代碼更適合你的風格。預處理代碼 (Preprocessor) 在代碼編譯之前被提前處理。預處理代碼均由一個井號 (#) 打頭。
1. 關于 #define
#define
聲明主要用于將常量(或字符串)賦予有意義的名字,比如當你在編寫一個日歷程序時,可以定義:
#define MONTHS_PER_YEAR 12
請注意格式。#define
命令之后為常量名,再之后為所賦的代替值,用空格隔開,結尾不需分號。
#define 常量名 代替值
通常情況下,習慣將預處理的常量名全大寫,單詞之間用下劃線隔開(與正常變量區分)。這樣做的原因是在編譯器處理這段 #define
代碼時,會自動尋找空格,空格之后的被認為是代替值。這也是為什么在每一行代碼的末尾不用加分號的原因,因為如果加了分號,分號本身也會被認為是代替值的一部分。
一個被定義的常量名并不是一個變量;它的值一旦被定義,便不能再被改變。 #define
聲明通常位于一個文件的頂部,緊接在 #import
文件導入定義之后。需要注意的是, #define
聲明必須位于常量名使用之前(不像方法 (method) 可以放在文件中任意位置)。
使用 #define
的另一個例子是儲存一些有意義的數值, 比如
#define PI 3.141592654// 計算圓的面積使用 "PI * radius * radius" 即可
,這比處處書寫 3.141592654 要方便許多。(改起來也快很多)
2. 更高級的用途
注意,預處理代碼起的作用實際上相當于在編譯之前,在整個代碼中進行了一次“搜索、替換”功能。這意味著 #define
有許多更復雜、更高級的用途。
我們先從 2π 開始,將 TWO_PI
定義為 2π:
#define TWO_PI 2.0 * 3.141592645
由于我們之前曾定義過 π,我們同樣可以在定義中使用定義后的常量名來指代:
#define TWO_PI 2.0 * PI
除了常量以外,你還可以利用預處理定義 Objective-C 代碼中任意一段字符或字符串,例如:
#define AND &&#define OR ||#define EQUALS ==if (y EQUALS 0 OR y EQUALS 1) // …
合理地利用 #define
,可增強代碼的可讀性。對比下列兩行代碼:
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))// 或#define IS_LEAP_YEAR (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)if (IS_LEAP_YEAR) // 代碼可讀性更強。
一個定義通常應在一行代碼中完成。但如果你需要手動空行,那么在每行后輸入一個后劃線(/)即可將幾行代碼連接起來成為一行。例如:
#define IS_LEAP_YEAR(y) (y % 4 == 0 && y % 100 != 0) /|| (y % 400 == 0)if ( IS_LEAP_YEAR(currentYear) )
3. 宏
#define
聲明中還可以使用參數,并且可使用多個參數;這一特性被稱為“宏”:
如:
#define SQUARE(x) ( (x) * (x) )
此時, y = SQUARE(v + 1);
等價于 y = ( (v + 1) * (v + 1) );
。
兩個參數
例如,你可以定義:
#define CalcInterest(x,y) ( x * y )
代碼中便可書寫:
int earnings = CalcInterest(10,5));
多個參數
例如,在代碼中,你需要頻繁使用 [NSArray arrayWithObjects: object, ..., nil]
這一命令。利用#define
,你可以簡化代碼:
#define Array(FIRST, ...) [NSArray arrayWithObjects: FIRST, ##__VA_ARGS__, nil]
其中 ##__VA_ARGS__
用于表示省略號所代表的所有內容。
4. # 算符以及 ## 算符
# 算符可產生一個 C-語言 格式的字符串。如:
#define string(x) #x //則 string(testing) == "testing"
## 算符用來連接兩段字符串。假設你有一組變量,x1
到 x100
。如果你想打印其中某一個變量的值。你可以這樣定義:
#define printxvar(n) printf("%i/n", x ## n)
由此, printxvar(20);
在編譯時將被識別為 printf(“%i/n”, x20);
。這樣只需要輸入 printxvar(n);
便可以打印出 xn
的值。
其實,##最常用的用途還是上面介紹的 ##__VA_ARGS__
,它可用來抓取省略號所代表的所有內容。