美文网首页
宏定义 #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
*/

相关文章

  • C语言特性(预处理)

    预处理 使用#define、#undef执行宏定义 #define的作用就是为字符串起个名字关于宏定义,有如下注意...

  • C语言 预处理指令

    一 .宏定义 #define 宏定义宏定义会在预处理的时候,用宏定义的值来替换宏的名称 定义格式 "#define...

  • 准备:回顾c

    宏定义 关键字 define 定义一个常量的方法(即宏定义) 带参数的宏定义 宏函数的定义 使用宏函数的好处是,不...

  • block中解决循环引用(常用的宏定义)

    定义宏:使用前提条件,定义一下宏 #define WeakSelf(weakSelf) __weak __type...

  • 宏定义 #define 的使用

    宏定义实现 执行重复动作 从 ReactiveObjC 中看到的, 然后自己理解下,写了一个简单的 实现的效果

  • IOS如何获取设备的宽和高

    这里使用的是宏定义: #define SCREENHEIGHT [UIScreen mainScreen].bou...

  • C 语言之宏定义与条件编译

    一. 宏定义 #define PI 3.141592653 //无参宏 #define SUM(a,b) a + ...

  • 宏和条件编译的结合使用

    宏 宏定义 有参数 无参数 1.无参数的宏 语法: #define 宏名 宏值 #define MM 10 //...

  • Swift中的条件编译

    1、条件编译2、宏定义define 1、条件编译 Swift中没有宏定义的概念,因此我们不能使用#ifdef的方法...

  • 宏定义 define

    // 宏定义 define // Swift 中宏定义被去除了,取代的是 let 或者 get 属性 // 例如 ...

网友评论

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

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