do {} while(0)的妙用

do {} while(0)的妙用

转自

[https://blog.csdn.net/qq_16777851/article/details/80867981](https://blog.csdn.net/qq_16777851/article/details/80867981](https://blog.csdn.net/qq_16777851/article/details/80867981](https://blog.csdn.net/qq_16777851/article/details/80867981 )

  • 避免空的宏定义在声明时出现警告

#define FUNC 
 
#define FUNC do{}while(0)
  • 避免出现歧义代码

#define FUN1(x)  x=1;x++;
 
if(...)
    FUNC1();

上面宏在使用时,展开后:

if(...)
	x = 1;
	x++;

有些风格的代码只有一个语句的if会省略{},这样导致了仅x = 1;受if逻辑控制,与原意违背。但是有人可能针对上面的宏定义做一些改进:

#define FUN1(x)  {x=1;x++;}

如果引用出代码是:

if(...)
	FUN1(x);
else
	xxxx;

展开后会多出一个;,导致编译不通过。

if(...)
{
	x=1;
	x++;
} ;
else
	xxxx;

如果是用do{}while(0),看看展开后的效果

#define FUN1(i) do{i=1;i++}while(0)

if(...)
	do{i=1;i++}while(0);
else
	xxxx;

语句块恰好被{}包含,而整个do{}while(0);又恰好可以看做一个语句,不会出现编译错误。

  • 某些情况下避免使用goto语句

int *p_int = NULL:
 
    p_int = malloc(100*sizeof(int)) ;
    if(!p_int)
    {
        return -1;
    }
 
    //return 0 suceess
    if(!func1())
    {
        free(p_int);
        return -1;
    }
 
 
    //return 0 suceess
    if(!func2())
    {
        free(p_int);
        return -1;
    }
 
    ...
    
    free(p_int);

上面这段代码在申请内存后,在多个出错处理里面要调用free来释放内存,有一种改进方法是使用goto语句,像内核驱动代码通常这样做:

  int *p_int = NULL:
 
    p_int = malloc(100*sizeof(int));
    if(!p_int)      goto err;
 
    //return 0 suceess
    if(!func1())    goto err;
 
 
    //return 0 suceess
    if(!func2())    goto err;
 
    ...
    
    free(p_int);
    return 0;
 
err:
    free(p_int);
    return -1;

可以看到,是用goto语句代码简洁了很多,但在代码复杂的一定程度后,有多个goto代码就显得比较乱了。这时候就可以是用do {}while(0)来处理了。(个人感觉和goto差不多,如果出错的处理方式不同,那么显然用goto才可以解决)

 int *p_int = NULL:
 
    do
    {
        p_int = malloc(100*sizeof(int));
        if(!p_int)      break;
 
        //return 0 suceess
        if(!func1())    break;
 
 
        //return 0 suceess
        if(!func2ii)    break;
 
        ...
 
        free(p_int);
        return 0;
    }
    while(0)
 
    free(p_int);
	return -1;
  • 提供代码块作用域

可以用于自定义变量,不怕和外面名重复。

原文地址:https://www.cnblogs.com/thammer/p/12531878.html