程序员iOS Developer

宏的“奇妙漂流”

2017-04-14  本文已影响688人  ccSundayChina

最近因为种种的机缘巧合,在阅读ReactiveCocoa的源码,然后就被它里面对宏的神奇使用所折服了,我想从此将踏上不归之路。。

扬帆起航.jpg

RAC中有一个RACmetamacros.h文件,这个文件里定义了大量的宏,里面对宏的使用到了出神入化的地步,可以在预处理时就得到可变参数个数,可以在书写RAC(obj,x)的时候,就自动提示出obj对象的属性x。今天我们就简单的学习一些关于宏的基础知识,然后举几个例子来具体的分析一下。

首先是关于宏里面各种符号意义的介绍,下面所列出来的是相对比较常见的。

有了以上的这些基础知识,我们先来看一个比较简单的例子。(例子来源于孙源大神的一篇文章,可惜没有注释,可能大伙看了也不明白是怎么出来的。。)

[Macro]预处理时计算可变参数个数
#define COUNT_PARMS2(_a1, _a2, _a3, _a4, _a5, RESULT, ...) RESULT
#define COUNT_PARMS(...) COUNT_PARMS2(__VA_ARGS__, 5, 4, 3, 2, 1)
int count = COUNT_PARMS(1,2,3); // 预处理时count==3

下面就来一步步分析一下是怎么在预处理的时候通过宏得到count的个数的。

带着疑问,我们继续看个更复杂一些的----ReactiveCocoa中的metamacro_argcount宏,这也是一个用来在预编译的时候求可变参数个数的宏。

先看一下它的定义
#define metamacro_argcount(...)  metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define metamacro_at(N, ...)  metamacro_concat(metamacro_at, N)(__VA_ARGS__)
#define metamacro_concat(A, B) metamacro_concat_(A, B)
#define metamacro_concat_(A, B) A ## B
#define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__)
#define metamacro_head(...)  metamacro_head_(__VA_ARGS__, 0)
#define metamacro_head_(FIRST, ...) FIRST

我们假设int a = metamacro_argcount(1,2, 3);//a = 3
看这个是怎么一步一步的计算出来的。步骤跟上面的那个简单例子基本一致。

注意我们为了书写方便,在此用X替代20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1

需要注意的一点是,我们所输入的可变参数的个数是有最大值限制的,比如刚刚RAC中的最大可变参数数目是20,如果我们输入的超过了20的话,那么就会出现错误。

如果看到这里,你没有蒙圈的话,那么恭喜你已经初步进入“宏”的奇妙漂流中了,之后会加入对它的数学分析。。

要相信这只是一扇打开更广阔世界的门而已。。
上一篇下一篇

猜你喜欢

热点阅读