“#”的迷雾
http://blog.csdn.net/woohyuknrg/article/details/17263811
?
在代碼中使用Autolayout時,大家都會使用NSDictionaryOfVariableBindings這個宏,這個宏可以生成一個變量名到變量值映射的Dictionary。比如NSDictionaryOfVariableBindings(button1, button2)將會生成一個{ @"button1" = button1, @"button2 = button2 }的Dictionary。它是怎么做到的呢?我們來看看這個宏的定義:
#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)這個宏定義中有3個參數,后兩個參數不難理解,但第一個參數中間有個#符號,語法上看起來比較怪異,這個是什么呢?以前在做越獄的mobilesubstrate開發時,其中定義的一堆宏頻繁使用了這個符號,下面就來揭開#這個符號在宏定義中的迷霧。
預編譯的一些知識
我們的代碼在build時并不是直接進行編譯的,在編譯之前還進行了預編譯處理。預編譯會把include或import的文件導入到文件中,同時會將代碼中用到的宏進行替換。注意宏是直接在代碼中替換成宏的定義的,如果有嵌套也會逐層替換。
“#”指示一些預編譯命令
預編譯命令一般都是以#開頭的,比如#include、#import、#if等,在這里就不一一說明了,本文主要說明一下#在宏定義里面的一些作用。
宏參數字符串化
在一個參數前加一個#,預處理時將會變成這個參數名的字符串常量,即字符串化(stringify)。比如:
#define GET_NAME(X) #X int a = 0; NSLog(@"%s",GET_NAME(a)); //output: "a" NSLog(@"%s",GET_NAME(a+3)); //output: "a+3"將會得到以下輸出:
a a+3可以看出#,將參數原樣轉換成字符串常量,如果參數是一個表達式,那么輸出這個表達式的原樣字符串常量。
回頭再看看NSDictionaryOfVariableBindings的定義:
#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)如果這樣生成兩個button的映射:
NSDictionaryOfVariableBindings(button1, button2);那么預編譯時就會轉換成:
_NSDictionaryOfVariableBindings(@"""button1, button2", button1, button2, nil);由于兩個常量字符串放在一起就是字符串常量串聯,將變成兩個字符串常量組合在一起的字符串常量,也就是上面是一個空字符串""和"button1, button2"串聯,所以上面的代碼等價于:
_NSDictionaryOfVariableBindings(@"button1, button2", button1, button2, nil);那么_NSDictionaryOfVariableBindings函數就可以將它的第一個參數按逗號,分割開作為key,后面就是各個key對應的值了。因此這段代碼就創建了一個內容為{ @"button1" = button1, @"button2 = button2 }的Dictionary。
?
可選可變參數
##在宏定義中可以放在__VA_ARGS__之前表示可變參數可以為空,否則的話可變參數至少為一個了。
#define MYLOG(format, ...) NSLog(format, ##__VA_ARGS__) MYLOG(@"Don't make an error!");上面代碼中MLOG中只有一個參數,如果不加##,則MLOG至少需要兩個參數,在Xcode里將會出現編譯錯誤。
轉載于:https://www.cnblogs.com/Keys/p/5130996.html
總結
- 上一篇: PaintCode 教程1:动态绘制按钮
- 下一篇: 【Java数据结构】线性表