2012-06-28 48 views
2

我一直在閱讀有關在iOS中使用#define宏的衝突信息,以及它們是僅在編譯時運行還是在運行時運行。在iPhone/iPad上正確使用宏#define

考慮我的情況:我想定義返回關於屏幕是大尺寸還是小尺寸的BOOL宏,這裏是代碼:

#define TTThisScreenWidth [[UIScreen mainScreen] bounds].size.width 
#define TTLargeScreenTrushHold 700.0f 
#define TTScreenIsOfLargeSize (TTThisScreenWidth > TTLargeScreenTrushHold) 

問題:如果這個代碼只在編譯時運行的屏幕大小將固定在它被編譯到的設備上,並且在具有不同屏幕的設備上運行時不會返回正確的答案。

但是,我檢查了它,它工作正常最初在iPad上編譯時(通用應用程序)

SO:安全嗎?

謝謝!

回答

4

宏指示C預處理器用其名稱替換其值。它不運行方法或函數,也不運行任何其他複雜的東西。在你的代碼,如果你用你的宏TTScreenIsOfLargeSize像這樣:

if (TTScreenIsOfLargeSize) { 
    /* ... */ 
} 

這實際上計算結果爲:

if ([[UIScreen mainScreen] bounds].size.width > 700.0f) { 
    /* ... */ 
} 

因爲[UIScreen mainScreen]等是在編譯時評估。

5

宏在編譯時替換爲;它們在編譯時不會運行。宏的主體將被「粘貼」,而不是對宏的名稱的引用,就像您手動輸入它一樣。

一般來說,編譯器會在編譯時使用或不使用宏來評估10。您的TTThisScreenWidth不涉及常量表達式 - 它是運行時表達式,所以它在運行時進行評估。

1

#define是用來定義常量和宏

它是如何工作的預編譯direvative:

考慮您的.m文件

NSString *str = [NSString stringWithFormat:MYSTRING, MYINT]; 
//What really happens is 
NSString *str = [NSString stringWithFormat:@"number is %d", 5]; 

每一這個例子

#define MYINT 5 
#define MYSTRING @"number is %d" 

define被替換爲它定義的值或代碼

1

這裏應該注意的是,儘管#if,#ifdef,#endif等情況下的C預處理引擎更多,但在指定問題的情況下,預處理器引擎的工作原理與一個TEXT替換引擎。

這就是爲什麼讓時說,一個不一樣的東西:

#define varA 10 
#define varB 20 
#define addAB varA + varB 

如果在真正的編譯代碼將與「翻+ varB」代替,以一個ADDAB電話。它始終將進行數學運算,然後很好的做法如下:

#define addAB (varA + varB) 

爲什麼是這樣的: 如果我簡單地使用ADDAB的第一個定義,那麼如果我不喜歡的東西:

myVar = 5 * addAB; 

則文本替換引擎將使它看起來像:

myVar = 5 * varA + varB; 

之前編譯。如果最初的意圖是在乘法之前首先添加a和b,那麼這不會是你的結果。如果使用第二個,則:

myVar = 5 * (varA + varB); 

成爲編譯之前的結果表達式,這會得到你想要的。記住在這些情況下的預處理器是一個簡單的文本替換引擎將讓你遠離。