do{}while(0)的用法

这几天在看代码的时候遇到了一个好像很神奇的用法:do{ … }while(0)。

do{ … }while(1)我能理解,就是一直循环,然后在循环体内设置跳出条件,或者干脆就不跳出。
那do{ … }while(0)是干嘛的呢?在内部也改变不了循环条件,然后执行一次就结束,那不就是没循环嘛?

赶紧查了一下,原来,这种用法主要是针对宏定义使用的。

这里我们来看一下如下代码:

#define INCREASE_TWO_VARIABLE(a, b)  a++;\
    b++;

我们定义了一个宏,其中包含了两条语句。看上去好像没什么问题。岁月静好,风平浪静。

但是,再考虑如下情景:

if(some_condition)
    INCREASE_TWO_VARIABLE(x, y); //请记住这个分号
else
    do_something;

嗯???好像哪里不对??我们把宏定义拆开:

if(some_condition)
    x++;
    y++;; //这里两个分号一个是宏定义内部的,一个是宏定义外部的。但是此时这里并不会报错,两个分号是可行的
else    //报错,没有对应的if语句
    do_something;

哎,这里就出现问题了,如果if后面不加大括号,那么只能跟一个语句,其他语句将被视为条件体之外的语句。那么此时,不仅y++一定会被执行,而且else没有对应的if语句,还会报错。(此时还好else会报错,不然编译通过,你却发现程序怎么都跑不对)

那咋办呢?不如我们用大括号把它括起来吧!于是我们修改了宏定义成这个亚子:

#define INCREASE_TWO_VARIABLE(a, b)  {\
    a++;\
    b++;\
}

然后刚才的情景就变成了:

if(some_condition)
{
    x++;
    y++;
};
else    //报错
    do_something;

嗯???不是?这个大括号后面的分号是怎么肥四!你在使用宏定义的时候后面就不能不加分号嘛!(请注意最开始的那个分号)

使用者:不,我不可以,我是强迫症!而且不加分号,VS会自动把else缩进4个空格,我还要手动删!

…………于是这个时候,你想起了传说中的do{ … }while(0)。于是你又把宏定义做了一个小小的修改:

#define INCREASE_TWO_VARIABLE(a, b)  do{\
    a++;\
    b++;\
}while(0)

于是刚刚的情景又变成了:

if(some_condition)
	do{
	    x++;
	    y++;
	}while(0);
else
    do_something;

于是编译又通过了,世界又恢复了和平。

此外,其实do{ … }while(0)还有另一种用法,虽然我依然觉得好像没什么卵用

if(condition1){
    do_something();
}
if(condition2){
    do_something();
}
if(condition3){
    do_something();
}
if(condition4){
    do_something();
}

这个时候do_something()会被各种执行,如果这一段代码非常复杂,那么看起来就会非常冗余。
虽然你可以使用宏定义将这些代码合在一起,也可以将condition合在一起变成一个if语句,但是你觉得使用宏定义不爽,合在一起又太乱,所以决定使用do{ … }while(0)。

do{
    if(condition1){
        break;
    }
    if(condition2){
        break;
    }
    if(condition3){
        break;
    }
    if(condition4){
        break;
    }
}while(0)
do_something();

所以总结来说:其实,do{ … }while(0)就是满足强迫症的,不接受反驳,over。
(其实这种用法应该是用来提高代码的一致性,是一种非常好的编程习惯,因为使用者并不会知道你这个宏的结尾该不该加分号)

(如有错漏,还望指摘)

原创文章 34 获赞 41 访问量 5959

猜你喜欢

转载自blog.csdn.net/qq_44844115/article/details/102566648