宏定义 #define 的使用

宏定义实现 执行重复动作

从 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 的使用)