1. 来两个简单的宏定义
#define metamacro_head(FIRST,..., 0) FIRST
意义比较明显没难度取第一个传入的参数;如 metamacro_head("a","b","c");取值为"a"
#define metamacro_concat_(A, B) A ## B
“##” 在宏定义里面表示字符的链接;metamacro_concat_("test","1") 张开后为字符串"test1";所以该宏业很简单,我们知道是参数的拼接了。
用的稍微复制点
2. 宏的调试
我们知道从代码到可执行会经历,1.预处理替换;2.词法分析;3.语法分析;4。IRCode生成;5.再到针对平台的汇编; 6.生成o文件; 7.生成可执行文件。现在我们关注的是第一个步骤。这样也能方便我们查看替换后的效果。虽然不能断点调试。
- (void)viewDidLoad {
[super viewDidLoad];
metamacro_head("a","b","c");
}
2.1 预处理替换前
image.png2.2 预处理替换后
- (void)viewDidLoad {
[super viewDidLoad];
"a";
}
//metamacro_head("a","b","c"); 被替换为“a”了。
3. 继续深入
3.1 简单定义
#define metamacro_at0(...) metamacro_head(__VA_ARGS__)
metamacro_at0可以看出metamacro_head一样。
#define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__)
metamacro_at1("a","b","c"); 对号入座 "a"=> _0; "b","c"=>... ; 三个点表示参数可以无线扩展,"VA_ARGS"表宏定义头的可变参数就是那三个点;我们展开metamacro_at1("a","b","c");
宏就变成了metamacro_head("b","c");那么根据上面描述我们知道metamacro_head是取第一个参数,因此metamacro_at1("a","b","c")的值是"b"。
3.2 继续推导
#define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at3(_0, _1, _2, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at4(_0, _1, _2, _3, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at5(_0, _1, _2, _3, _4, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at6(_0, _1, _2, _3, _4, _5, ...) metamacro_head(__VA_ARGS__)
#define metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) metamacro_head(__VA_ARGS__)
..............
#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__)
可以知道metamacro_at + 整数,整数是多少就是该宏取到第几位参数!
3.2 抽象 “metamacro_at + 整数”
#define metamacro_at(N, ...) \
metamacro_concat(metamacro_at, N)(__VA_ARGS__)
举例:
metamacro_at(1,"a","b","c");我们知道metamacro_concat为两个产生拼接,那么metamacro_at(1,"a","b","c"),展开为metamacro_at1("a","b","c");那我们就知道了其结果为"b";metamacro_at2(,"a","b","c"),展开后值就是"c"了。依次类推就容易明白metamacro_at(N, ...), 是取后面可变参数"..."的第N个参数了[N从0开始计算]。
到现在为止我们可以获取宏定义参数的任何为止的参数了!
4.计算宏参数个数
4.1 metamacro_argcount
也就是我们今天的主角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)
4.2 metamacro_argcount推导
经过我们上面的分析已知道晓metamacro_at的含义。
举例:
metamacro_argcount("a","b","c")
=>
metamacro_at(20, "a","b","c", 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
=>
3
“3”,便是我们所传入参数的个数,目前该宏设计为最多能传入20个参数。
4.3 巧妙的设计:
metamacro_at19(20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
含义:metamacro_at19表示取第19号参数,第20个也就是最后一位参数1。
metamacro_at20(20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
含义:我们有1到20总共20个参数,取不到参数值,因为metamacro_at20取的是第20号[从0算起],第21个参数。
metamacro_at20("a",20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
含义:metamacro_at20是取第21个参数的,现在我们有21个参数,取到的值是多少呢?很显然第21个参数为最后1,自己从头开始数一数;
metamacro_at20("a","b",20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
含义:现在我们有22个参数而metamacro_at20是取第21个参数,我们数过来就知道了结果为2;
到这里是不是恍然大悟。只要我们填的参数不超过20个就能通过metamacro_argcount宏算出所传入的参数个数!
网友评论