美文网首页
宏定义中的do...while(0)用途

宏定义中的do...while(0)用途

作者: 翻滚着的牛宝宝 | 来源:发表于2016-06-06 17:41 被阅读658次

最近在考哪代码时经常碰到do...while(0)这种「奇怪」的定义方式,例如:
#define ComConfigOpStatsResetDownload(opState)
do {
(opState) &= ~(ComConfigOpStateDownload);
} while(0)
看到之后很疑惑,为什么这样写呢那个?岂不是多次一举。之后仔细一想,确实有深意,结合后来查阅资料,总结这样写有以下几点好处:

  • 避免if-else代码块匹配错误。如果不使用do...while(0),如下
    #define PRINT_LOG(str)
    if(DEBUG)
    NSLog(str)

    那么如果调用该宏时如下:
    if(message == nil)
    PRINT_LOG(@"message is nil");
    else
    [label setText:message];

    看起来貌似没问题,但是事实上宏定义展开后就成为了:
    if(message == nil)
    if(DEBUG)
    NSLog(@"message is nil");
    else
    [label setText:message];
    很明显,else没有匹配到我们想匹配的地方。而这种问题又是很难发现的,确实比较坑。当然,我们如果用do...while(0)将宏定义包裹起来就不会有这样的问题了,使用do...while(0)包裹后展开代码将会是:
    if(message == nil)
    do{
    if(DEBUG)
    NSLog(@"message is nil");
    }while(0);
    else
    [label setText:message];
    是不是很cool。哈哈。

  • 避免上下文匹配错误。其实和第一点类似,举个栗子:
    #define SWITCH_A_B(A,B) int temp = B;B = A;A = temp;
    调用时候如下:
    if(isNeedSwitch)
    SWITCH_A_B(numA, numB);
    宏展开之后就是:
    if(isNeedSwitch)
    int temp = B;
    B = A;
    A = temp;;
    匹配错误!如果使用do...while(0)定义即可解决。
    看了上面两点,如果你是一个善于思考的boy(or girl),那么你可能要说,为什么不用{}来包裹呢?如果用{}包裹,也会出现上下文混淆,例如下面:

     #define SWITCH_A_B(A,B) {int temp = B;B = A;A = temp;}
    

    那么,假如我的调用部分是这样:
    if(isNeedSwitch)
    SWITCH_A_B(A, B);
    else
    NSLog(@"its ok"); 看起来没什么问题,展开后又出问题了: if(isNeedSwitch) { int temp = B; B = A; A = temp; }; else NSLog(@"its ok");

    对,没错,多出一个';',直接导致我们编译不过。

  • 上面说到,第二点中代码展开会多出一个';'。没错,do...while(0)的第三个好处就是相当于在宏定义中有一个block(代码块)来盛放大段代码,形成一个语法单元,不会造成上下文混淆,调用时候看起来更像函数调用,不会多出';'。

  • 第四个原因就是我们一些宏可能会是空的,例如
    if(DEBUD)
    #define PRINT_TIME NSLOG(@"time:%@",stime);
    else
    #define PRINT_TIME
    这样可能会出现讨厌的warning,所以,我们就可以写成:
    if(DEBUD)
    #define do{PRINT_TIME NSLOG(@"time:%@",stime);}while(0)
    else
    #define PRINT_TIME do{}while(0)
    如此,我们就轻松解决了warning问题。


综上,在复杂代码块的宏定义以及涉及if判断的宏定义,最好使用do...while(0)包裹起来。同shi,从上面的例子中,你可能也注意到在if-else代码块最好养成使用'{}'的习惯,能够避免上下文混淆问题(这类问题也是相当难查的)。ok,今天就写到这里,希望对你有用,欢迎各位补充指教。

相关文章

  • 宏定义中的do...while(0)用途

    最近在考哪代码时经常碰到do...while(0)这种「奇怪」的定义方式,例如:#define ComConfig...

  • do...while(0)在宏定义中的巧妙用法

    大家都知道,do…while(condition)可以表示循环,但你有没有遇到在一些宏定义中可以不用循环的地方,也...

  • swift&&OC

    宏定义 OC中的宏定义 swift中的宏定义 OC中宏定义的方式,在swift中是不可用的,在swift中,宏定义...

  • 宏定义中的do{.....}while(0)

    转载自:http://www.cnblogs.com/lanxuezaipiao/p/3535626.html 使...

  • ndk_android_log

    0x01:导入头文件 0x02:简单使用 0x03:使用宏定义 0x04:使用宏定义后的内容 0x05:源码 0x...

  • 关于list_for_each_entry相关函数

    offsetof宏 定义: 该宏先将0转换成TYPE型指针,即形成一个指向地址0的TYPE指针,然后对TYPE中的...

  • c高级自我学习(1)

    1 编译预处理和宏定 #undef指令删除前面定义的宏定义。 无参宏定义:宏名中没有参数。 1,宏定义中宏名用来表...

  • 宏定义&枚举

    宏定义 (#define)宏定义的意义和用途:(习惯上,都是“k”开头)1.为了让一些数据有意义。 枚举 (enu...

  • 21_宏定义的使用与分析

    关键词:定义宏常量、宏定义的表达式、宏表达式与函数的对比、强大的内置宏 0. 对于宏的第一印象: 1)可以定义一...

  • 宏定义中do{...}while(0)的作用

    之前在书上和网上看到过很多次关于do{...}while(0)作用的文章了,最近看Linux内核源码的时候发觉这个...

网友评论

      本文标题:宏定义中的do...while(0)用途

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