跳转至

为什么要使用do-while(0)

从语义上理解,do {...} while(0)内的逻辑就只执行一次,并没有循环执行,粗略看来,似乎画蛇添足了,那么为什么还需要在只执行一次的逻辑外面加上一层do {...} while(0)语句呢?实际上,在这些逻辑中使用do {...} while(0)的作用远大于美化你的代码,下面就来看看实际的使用场景。

定义一个作用域,避免替换的时候出错

//例如,现在有一个宏定义如下
#define DEMO  funA();funB()

//现在需要其在一个if语句后做替换
if(1==a)
DEMO ; 

//展开后就成了
if(1==a)
  funA;
funB;

//有时候也是使用{}进行定义
#define DEMO  {funA();funB()}

//但是因为实际使用时有时会加上 ; 就会导致其展开后变为
if(1==a)
{
  funA;
  funB
};//后面万一有else就会导致错误

//此时可以使用do{···}while(0)
#define DEMO  do{funA();funB()}while(0)

//展开后就为
if(1==a)
do{
  funA;
  funB
}while(0);

避免goto语句的使用

//在实际使用中或出现有单层多个if分支需要跳出的情况,此时可以使用goto语句
//但是为了程序结构的清晰,还是要尽量限制goto语句的使用,
//我们可以使用do {...} while(0)结构配合break跳出单层的循环的方法来替代这种goto的用法。
do{
  if(条件)
    {
    ···
    break;
    }
  ···
}while(0);

定义一个单独的函数块来实现复杂的操作

//当某个函数程序功能较为复杂,在该函数的代码段中如果不再单独定义一个函数实现部分逻辑,
//可以使用do {...} while(0)作为一个代码块,将想要实现的逻辑放在do {...} while(0)中,
//同时在该在do {...} while(0)代码块中定义的变量,
//可以不用考虑和函数之前或者之后的变量名重复冲突的问题。
//但是为了代码的易读性,还是尽量声明不同的变量名。

避免空宏的警告

//有的时候,程序为了不同的平台移植或者不同架构的限制,很多时候会先定义空宏,
//后续再根据实际的需要看是否定义具体内容。但是在编译的时候,这些空宏可能会给出warning,
//为了避免这样的warning,我们可以使用do{...}while(0)来定义空宏,
//这种情况不太常见,因为有很多编译器已经支持空宏。