OC基礎9:預處理程序

1、  關於#define語句:

(1)、#define語句的用途就是給某個符號名稱指定一個程序要用到的常量,比如:

#define TRUE 1

這個語句的意思就是把TRUE指定爲1,那麼後續的程序中如果需要用到1來做判斷或者計算,就可以直接使用TRUE這個符號名稱了;

   (2)、預定義名稱不是變量,所以不能在程序過程中給它賦值,不能改變它的值;

   (3)、注意#define語句沒有用到等號,也不需要分號結尾,如果結尾加上分號的話,那麼這個常量的值就會變成你想要的值和一個分號的合併了,即是這個分號也會被和值同時替換到這個預定義名稱中;

   (4)、#define語句一般寫在程序開始的地方,在#import和include語句後面,但是其實它可以出現在程序的任何位置,只要出現在程序引用它的位置之前即可;

   (5)、預定義名稱和變量不同,它沒有局部作用域這個概念,你可以在程序中任何位置使用你定義過的預定義名稱。一般把它放在頭文件中,以便在多個源文件中使用它們;

   (6)、使用預定義名稱來代替常量值,這樣增加了程序的可讀性,能清晰地看到某個常量的含義以及它的用途。同時如果使用了這種方法定義常量,然後在程序中發現這個常量出錯了,那麼你只需要修改#define語句,而不需要整個程序去查找這個常量出現的地方並一個一個修改;

   (7)、一般來說預定義名稱有兩種命名習慣:一種是全部字母都大寫,比如(1)的例子,一種是以k開頭,比如(1)的預定義名稱也可以寫作kTrue。

 

2、其實編譯器在處理預定義名稱的時候,所做的僅僅是簡單的查找替換,編譯過程中把所有的預定義名稱替換成所定義的值;

 

3、在#define語句中還可以出現表達式,比如這個例子是合法的:

   #define TWO_PI 2.0*3.1415926

   也可以出現關係運算符,比如這個例子也是合法的:

   #define AND &

  

4、預定義的值本身可以引用另一個預定義的值,比如:

   #define PI 3.1415926

   #define TWO_PI 2.0*PI

   這種情況是合法的,設置把這個兩個語句的順序顛倒過來,也是合法的。

 

5、如果預定義的名稱或者值過長,甚至需要換行寫,那麼上一行的最後一個字符必須是反斜槓,如下例:

   #define XXX ( 2.0 * 5.0 + 31.0 * 7.0 ) \

   * 56.0

   這個表達式相當於( 2.0 * 5.0 + 31.0 * 7.0 ) * 56.0,注意是可以有空格的。

 

6、關於宏:

   (1)、可以讓預定義名稱本身帶着一個或多個參數,在編譯的時候,編譯器會自動把參數替換到預定義值的對應位置去。這種預定義成爲宏。如下例子:

   #define XXX(y) y * 2.0 + y / 5.0

   這個預定義允許你在代碼中寫出n=XXX(5); 這樣的語句;

   (2)、宏和方法不同,宏的參數是沒有類型的,僅僅只是執行字面意義上的替換。同時需要注意,在預定義名稱和參數列表的括號之間不允許有空格

   (3)、在定義宏時,參數列表內的每個單獨的參數都要打上括號,因爲宏只是執行字面意義上的替換,不打括號會有可能出錯。如果定義一個宏如下:

       #define SQUARE(x) x * x

       那麼當出現n=SQUARE(y+1)時,這個等式會被替換稱n=y+1*y+1,就與本來想求的值不同了。所以這個預定義應該寫爲:

       #define SQUARE(x) ((x) * (x))

       全部用括號括起來最保險,因爲你有可能會使用SQUARE(x)去和其他數值運算;

   (4)、甚至在宏的預定義值中可以調用方法,假設Fraction類有一個初始化的設值方法initWith:over:,那麼可以有以下宏定義:

       #define MAKE_FRAC(x,y) ([[Fraction alloc] initWith:x over:y])

   (5)、宏中允許出現判斷語句,比如:

       #define MAX(x,y) ((a) > (b)? (a): (b))

   (6)、宏中允許出現關係運算符,比如:

       #define IS_LOWER_CASE(x) ((x)>=’a’ && (x)<=’z’)

   (7)、甚至可以在宏中進行字符從小寫到大寫的轉換,如下例子:

       #define TO_UPPER(x) (IS_LOWER_CASE(x)? (x)-‘a’+’A’: (x))

 

7、可以把所有要用到的預處理定義收集到單獨一個h文件中,然後在程序中使用#import把它引入進來。一般使用雙引號引入。

 

8、使用雙引號引入文件,系統會在包括當前目錄在內的多個目錄查找引入文件;把文件名放在尖括號裏面,會導致系統只在“特殊”的系統文件目錄中查找包含文件。

 

9、關於幾個條件編譯語句:

   (1)、有時候系統需要使用到硬件的類型來作爲參數,比如某個頁面在iPad和iPhone上的顯示可能就會不同,需要顯示不同尺寸的圖片,那麼此時就需要判斷系統的某些參數。

       假設在一個iPad程序中已做了以下定義:

       #define IPAD 1

       那麼可以使用條件編譯語句進行如下判斷來選擇要顯示那張圖片:

       #ifdef IPAD

       # define kImageFile @”xxxIPad.png”

       #else

       #  define kImageFile @”xxx.png”

       #endif

       這裏就使用了#ifdef、#else和#endif這三個條件編譯語句進行了判斷;

   (2)、同時可以注意到(1)中,#define語句在井號和define之間可以出現空格;

   (3)、另外還有#if和#elif兩種語句,if語句用來判斷常量表達式是否爲0;

 

10、最後還有一個#undef語句,這個語句可以將一些已經定義過的名稱消除掉,恢復到未定義的狀態;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章