“#”的迷雾
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個參數(shù),后兩個參數(shù)不難理解,但第一個參數(shù)中間有個#符號,語法上看起來比較怪異,這個是什么呢?以前在做越獄的mobilesubstrate開發(fā)時,其中定義的一堆宏頻繁使用了這個符號,下面就來揭開#這個符號在宏定義中的迷霧。
預(yù)編譯的一些知識
我們的代碼在build時并不是直接進行編譯的,在編譯之前還進行了預(yù)編譯處理。預(yù)編譯會把include或import的文件導(dǎo)入到文件中,同時會將代碼中用到的宏進行替換。注意宏是直接在代碼中替換成宏的定義的,如果有嵌套也會逐層替換。
“#”指示一些預(yù)編譯命令
預(yù)編譯命令一般都是以#開頭的,比如#include、#import、#if等,在這里就不一一說明了,本文主要說明一下#在宏定義里面的一些作用。
宏參數(shù)字符串化
在一個參數(shù)前加一個#,預(yù)處理時將會變成這個參數(shù)名的字符串常量,即字符串化(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可以看出#,將參數(shù)原樣轉(zhuǎn)換成字符串常量,如果參數(shù)是一個表達式,那么輸出這個表達式的原樣字符串常量。
回頭再看看NSDictionaryOfVariableBindings的定義:
#define NSDictionaryOfVariableBindings(...) _NSDictionaryOfVariableBindings(@"" # __VA_ARGS__, __VA_ARGS__, nil)如果這樣生成兩個button的映射:
NSDictionaryOfVariableBindings(button1, button2);那么預(yù)編譯時就會轉(zhuǎn)換成:
_NSDictionaryOfVariableBindings(@"""button1, button2", button1, button2, nil);由于兩個常量字符串放在一起就是字符串常量串聯(lián),將變成兩個字符串常量組合在一起的字符串常量,也就是上面是一個空字符串""和"button1, button2"串聯(lián),所以上面的代碼等價于:
_NSDictionaryOfVariableBindings(@"button1, button2", button1, button2, nil);那么_NSDictionaryOfVariableBindings函數(shù)就可以將它的第一個參數(shù)按逗號,分割開作為key,后面就是各個key對應(yīng)的值了。因此這段代碼就創(chuàng)建了一個內(nèi)容為{ @"button1" = button1, @"button2 = button2 }的Dictionary。
?
可選可變參數(shù)
##在宏定義中可以放在__VA_ARGS__之前表示可變參數(shù)可以為空,否則的話可變參數(shù)至少為一個了。
#define MYLOG(format, ...) NSLog(format, ##__VA_ARGS__) MYLOG(@"Don't make an error!");上面代碼中MLOG中只有一個參數(shù),如果不加##,則MLOG至少需要兩個參數(shù),在Xcode里將會出現(xiàn)編譯錯誤。
轉(zhuǎn)載于:https://www.cnblogs.com/Keys/p/5130996.html
總結(jié)
- 上一篇: PaintCode 教程1:动态绘制按钮
- 下一篇: KindEditorckplayer的简