宏本身不難理解,但是往往嵌套多了,或者利用一些不常用的特性之后,會(huì)讓人覺得迷惑.
ProtocolKit中的一段宏定義
在ProtocolKit
中有這么一段宏的定義:
// Get container class name by counter
#define _pk_get_container_class($protocol) _pk_get_container_class_imp($protocol, __COUNTER__)
#define _pk_get_container_class_imp($protocol, $counter) _pk_get_container_class_imp_concat(__PKContainer_, $protocol, $counter)
#define _pk_get_container_class_imp_concat($a, $b, $c) $a ## $b ## _ ## $c
當(dāng)時(shí)知道:
##
連字符,通常用來拼接
__COUNTER__
計(jì)數(shù)器,一般用來后綴在變量上面,保證變量的唯一性.在程序中,每使用一次,這個(gè)數(shù)字就+1
,默認(rèn)是0
再看實(shí)際拼接的結(jié)果:
_pk_get_container_class(MyProtocol);
//相當(dāng)于
__PKContainer_MyProtocol_0;
一開始的時(shí)候在想, 不就是要拼接么,為何要弄那么多層嵌套.難道是故意增加復(fù)雜度,讓人覺得高深? 還有變量前面的$
,是和shell中的一個(gè)意思? 表示變量?
嘗試簡化
遇到看不懂的東西,我喜歡先去掉,把自己知道的代碼羅列出來.然后依次加上不懂得東西,看它對(duì)既有結(jié)果的改變.然后判斷它的作用.
于是,我寫了下面一個(gè)宏:
#define _kn_get_container_class(prefix,protocol) prefix##_##protocol##_##__COUNTER__
然后使用:
NSString * _kn_get_container_class(__kn,MyProtocol);
可是根據(jù)編譯器的警告來看,并不是我想要的結(jié)果:
原來在##
的作用下,__COUNTER__
被當(dāng)成了字面上的表示,并沒有解析.
然后,根據(jù)作者的寫法,把實(shí)現(xiàn)加深一層,改寫為:
#define _simpleifyGetContainerClass(prefix,protocol,counter) _simple_getContainerClass_imp(prefix,protocol,counter)
#define _simple_getContainerClass_imp(a,b,c) a##b##_##c
調(diào)用
NSString * _simpleifyGetContainerClass(__PKContainer_,MyProtocol,__COUNTER__);
發(fā)現(xiàn)結(jié)果正確.
我這種寫法,需要使用者傳遞多個(gè)參數(shù),也已經(jīng)必須嵌套一層了.作者在此基礎(chǔ)上加上默認(rèn)的參數(shù)實(shí)現(xiàn),也是很合理的.
另外可以看到,這個(gè)$
符號(hào),不加也可以,所以,個(gè)人猜想.這個(gè)和shell中使用變量
不是一回事.可能加上僅僅為了閱讀者明白,這個(gè)地方是個(gè)變量.若理解不正確,請(qǐng)您指正.
GCC中一個(gè)可變參數(shù)的宏
之前項(xiàng)目中,封裝過打印.當(dāng)時(shí)就用到了可變參數(shù)的宏:
#define GUIError(message,...) DDLogError(@"\n[ FILE ] %s \n[ METHOD ] %s\n[ LINE ] %d \n[ Message ]\n%@\n\n=======================================================\n",__FILE__,__FUNCTION__,__LINE__,[NSString stringWithFormat:message,## __VA_ARGS__])
就是在定義的時(shí)候,以...
作為最后一個(gè)參數(shù),使用的時(shí)候,__VA_ARGS__
就代指這一系列可變參數(shù).
今天想找找關(guān)于宏的資料,發(fā)現(xiàn)GCC的文檔中,也有關(guān)于可變參數(shù)宏的說明.在此,就不贅述了,想深入了解的,可以查看文檔