美文网首页
小记:那个宏metamacro_argcount

小记:那个宏metamacro_argcount

作者: 熊猫人和熊猫君 | 来源:发表于2018-07-21 16:34 被阅读0次

    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.png

    2.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宏算出所传入的参数个数!

    相关文章

      网友评论

          本文标题:小记:那个宏metamacro_argcount

          本文链接:https://www.haomeiwen.com/subject/ykphmftx.html