美文网首页
宏定义 #define 的使用

宏定义 #define 的使用

作者: Y筱鹏Y | 来源:发表于2020-05-09 13:51 被阅读0次

    宏定义实现 执行重复动作

    ReactiveObjC 中看到的, 然后自己理解下,写了一个简单的

    实现的效果

    #define INIT_MACRO(index, var) char var##index = 'a'
    #define char_init(...) jaz_macro_foreach(INIT_MACRO,;,__VA_ARGS__)
    
    
    char_init(d, e, f, g);  
    //上面语句在预处理之后,结果如下
    char d0 = 'a' ; char e1 = 'a' ; char f2 = 'a' ; char g3 = 'a';
    
    
    
    #define jaz_macro_concat(A, B) A ## B
    // 获取到传过来多个变量中的第一个
    #define jaz_macro_list_head(first, ...) first
    // 忽略掉前10个元素,取第11个元素的值
    #define jaz_macro_list_at10(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9, ...) jaz_macro_list_head(__VA_ARGS__, 0)
    // 拼接 jaz_macro_list_at 与 N(N=10) , 形成 jaz_macro_list_at10 宏的名字, 然后将剩余的参数传到 jaz_macro_list_at10 宏里面   
    #define jaz_macro_list_at(N, ...) jaz_macro_concat(jaz_macro_list_at, N)(__VA_ARGS__)
    // 用于计算传过来的参数的个数,最大可以计算10个参数
    // 原理是, 10 会用在 jaz_macro_list_at 里面的 N
    // 这个时候 __VA_ARGS__ 与 10,9,8,7,6,5,4,3,2,1 会一起传到 jaz_macro_list_at10 宏中
    // jaz_macro_list_at10 会忽略掉前10个参数,取第11个参数,所以 __VA_ARGS__ 有几个值
    // 第11个参数, 就是 10,9,8,7,6,5,4,3,2,1 中的 「数字」,
    // e.g.
    //      __VA_ARGS__ 有 两个值 a, b , 
    //      这个时候  __VA_ARGS__ 与 10,9,8,7,6,5,4,3,2,1 就会变成 a, b, 10,9,8,7,6,5,4,3,2,1
    //      所以第11个参数正好是 2 
    #define jaz_macro_list_args_count(...) jaz_macro_list_at(10, __VA_ARGS__, 10,9,8,7,6,5,4,3,2,1)
    
    // 默认的循环体
    #define jaz_macro_list_iter(INDEX, MACRO, VAR) MACRO(INDEX, VAR)
    
    // 可以构成循环的核心 开始, 就是层级调用
    #define jaz_macro_list_ctx_0(MACRO, SEP, CONTEXT) 
    #define jaz_macro_list_ctx_1(MACRO, SEP, CONTEXT, _0)  \
        MACRO(0, CONTEXT, _0)
        
    #define jaz_macro_list_ctx_2(MACRO, SEP, CONTEXT, _0, _1) \
        jaz_macro_list_ctx_1(MACRO, SEP, CONTEXT, _0) \
        SEP \
        MACRO(1, CONTEXT, _1)
        
    #define jaz_macro_list_ctx_3(MACRO, SEP, CONTEXT, _0, _1, _2) \
        jaz_macro_list_ctx_2(MACRO, SEP, CONTEXT, _0, _1) \
        SEP \
        MACRO(2, CONTEXT, _2) 
        
    #define jaz_macro_list_ctx_4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
        jaz_macro_list_ctx_3(MACRO, SEP, CONTEXT, _0, _1, _2) \
        SEP \
        MACRO(3, CONTEXT, _3)
        
    #define jaz_macro_list_ctx_5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
        jaz_macro_list_ctx_4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
        SEP \
        MACRO(4, CONTEXT, _4)
        
    #define jaz_macro_list_ctx_6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
        jaz_macro_list_ctx_5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
        SEP \
        MACRO(5, CONTEXT, _5) 
        
    #define jaz_macro_list_ctx_7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
        jaz_macro_list_ctx_6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
        SEP \
        MACRO(6, CONTEXT, _6)
        
    #define jaz_macro_list_ctx_8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
        jaz_macro_list_ctx_7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
        SEP \
        MACRO(7, CONTEXT, _7)
        
    #define jaz_macro_list_ctx_9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
        jaz_macro_list_ctx_8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
        SEP \
        MACRO(8, CONTEXT, _8)
        
    #define jaz_macro_list_ctx_10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
        jaz_macro_list_ctx_9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
        SEP \
        MACRO(9, CONTEXT, _9)
    // 可以构成循环的核心 结束
    
    // 包装一层,否则直接写成jaz_macro_concat(jaz_macro_list_ctx_,jaz_macro_list_args_count(__VA_ARGS__)) 这个样子存在问题
    // 此处最终会调用到 构成循环的核心 的10个宏中的其中一个,
    // 具体调用哪一个根据 ARGS 的值来决定, 如果为 1 则会将jaz_macro_list_ctx_与1 拼接在一起
    // 构成 jaz_macro_list_ctx_1(MACRO, SEP, CONTEXT, __VA_ARGS__)
    // 而 ARGS 的值 则是使用 jaz_macro_list_args_count(__VA_ARGS__) 取出来的
    #define __jaz_macro_foreach(MACRO, ARGS, SEP, CONTEXT, ...) jaz_macro_concat(jaz_macro_list_ctx_, ARGS)(MACRO, SEP, CONTEXT, __VA_ARGS__)
    
    // 外部可以使用的宏
    // 附带额外的参数版本
    // 
    // MACRO: 必须遵守 macro(index, context, var)
    //              index 下标, context 附带的信息与 CONTEXT 相同, var 传入的变量
    // SEP: 分割符号
    // CONTEXT: 附带的信息
    // ...: 其它变量
    #define jaz_macro_foreach_ctx(MACRO, SEP, CONTEXT, ...) __jaz_macro_foreach(MACRO, jaz_macro_list_args_count(__VA_ARGS__), SEP, CONTEXT, __VA_ARGS__)
    
    // MACRO: 必须遵守 macro(index, var)
    //              index 下标, var 传入的变量
    // SEP: 分割符号
    // ...: 其它变量
    #define jaz_macro_foreach(MACRO, SEP, ...) __jaz_macro_foreach(jaz_macro_list_iter, jaz_macro_list_args_count(__VA_ARGS__), SEP, MACRO, __VA_ARGS__)
    
    
    
    // 先定义一个正常的宏,遵守 MACRO 的限定格式
    #define INIT_MACRO(index, var) char var##index = 'a'
    // 定义出实际在代码中需要使用的宏 使用jaz_macro_foreach实现
    #define char_init(...) jaz_macro_foreach(INIT_MACRO,;,__VA_ARGS__)
    
    
    // 先定义一个正常的宏,遵守 MACRO 的限定格式
    #define INIT_MACRO_CTX(index, ctx, var) ctx char var##index = 'b'
    // 定义出实际在代码中需要使用的宏 jaz_macro_foreach_ctx实现
    #define char__const_init(...) jaz_macro_foreach_ctx(INIT_MACRO_CTX, ;, const, __VA_ARGS__)
    
    int main(int argc, char *argv[]) {
        char_init(d, e, f, g);  //  char d0 = 'a' ; char e1 = 'a' ; char f2 = 'a' ; char g3 = 'a';
        char_init(h, i, j); //  char h0 = 'a' ; char i1 = 'a' ; char j2 = 'a';
        char_init(k, l);    //  char k0 = 'a' ; char l1 = 'a';
        char_init(m);   //  char m0 = 'a';
        char__const_init(n, o, p , q);  //  const char n0 = 'b' ; const char o1 = 'b' ; const char p2 = 'b' ; const char q3 = 'b';
        return 0;
    }
    
    /**
    拿char__const_init(n, o, p , q); 举例
    1) char__const_init(n, o, p , q); => 
    2) jaz_macro_foreach_ctx(INIT_MACRO_CTX, ;, const, n, o, p, q); =>
    3) __jaz_macro_foreach(INIT_MACRO_CTX, jaz_macro_list_args_count(n, o, p, q), ;, const, n, o, p, q); => // jaz_macro_list_args_count(n, o, p, q) 如何等于 4 下面a1)来解释
    4) jaz_macro_concat(jaz_macro_list_ctx_, 4)(INIT_MACRO_CTX, ;, const, n, o, p, q); =>
    5) jaz_macro_list_ctx_4(INIT_MACRO_CTX, ;, const, n, o, p, q); =>
    6) jaz_macro_list_ctx_3(INIT_MACRO_CTX, ;, const, n, o, p) ; INIT_MACRO_CTX(3, const, q);
    7) jaz_macro_list_ctx_2(INIT_MACRO_CTX, ;, const, n, o) ; INIT_MACRO_CTX(2, const, p) ; INIT_MACRO_CTX(3, const, q);
    8) jaz_macro_list_ctx_1(INIT_MACRO_CTX, ;, const, n) ; INIT_MACRO_CTX(1, const, o) ; INIT_MACRO_CTX(2, const, p) ; INIT_MACRO_CTX(3, const, q);
    9) INIT_MACRO_CTX(0, const, n) ;  INIT_MACRO_CTX(1, const, o) ; INIT_MACRO_CTX(2, const, p) ; INIT_MACRO_CTX(3, const, q);
    10) const char n0 = 'b' ; const char o1 = 'b' ; const char p2 = 'b' ; const char q3 = 'b';
    
    a1) jaz_macro_list_args_count(n, o, p, q) =>
    a2) jaz_macro_list_at(10, n, o, p, q, 10,9,8,7,6,5,4,3,2,1) =>
    a3) jaz_macro_concat(jaz_macro_list_at, 10)(n, o, p, q, 10,9,8,7,6,5,4,3,2,1) =>
    a4) jaz_macro_list_at10(n,o,p,q,10,9,8,7,6,5, ...) jaz_macro_list_head(4,3,2,1, 0) => // ... 里面是 4,3,2,1
    a5) jaz_macro_list_head(4,3,2,1, 0) 4 //最终返回的是4
    */
    

    相关文章

      网友评论

          本文标题:宏定义 #define 的使用

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