do{...}while(0)的意义和用法

linux内核和其他一些开源的代码中,经常会遇到这样的代码:
do{
 ...
}while(0)

这样的代码一看就不是一个循环,do..while表面上在这里一点意义都没有,那么为什么要这么用呢?

实际上,do{...}while(0)的作用远大于美化你的代码。查了些资料,总结起来这样写主要有以下几点好处:

1、辅助定义复杂的宏,避免引用的时候出错:

举例来说,假设你需要定义这样一个宏:
#define DOSOMETHING()\
               foo1();\
               foo2();

这个宏的本意是,当调用DOSOMETHING()时,函数foo1()和foo2()都会被调用。但是如果你在调用的时候这么写:

if(a>0)
    DOSOMETHING();

因为宏在预处理的时候会直接被展开,你实际上写的代码是这个样子的:
if(a>0)
    foo1();
foo2();

这就出现了问题,因为无论a是否大于0,foo2()都会被执行,导致程序出错。


那么仅仅使用{}将foo1()和foo2()包起来行么?


我们在写代码的时候都习惯在语句右面加上分号,如果在宏中使用{},代码里就相当于这样写了:“{...};”,展开后就是这个样子:
if(a>0)
{
    foo1();
    foo2();
};

这样甚至不会编译通过。所以,很多人才采用了do{...}while(0);
#define DOSOMETHING() \
        do{ \
          foo1();\
          foo2();\
        }while(0)\
    
...
 
if(a>0)
    DOSOMETHING();
 
...

这样,宏被展开后,才会保留初始的语义。GCC提供了Statement-Expressions用以替代do{...}while(0); 所以你也可以这样定义宏:
#define DOSOMETHING() ({\
        foo1(); \
        foo2(); \
})

2、避免使用goto对程序流进行统一的控制:

有些函数中,在函数return之前我们经常会进行一些收尾的工作,比如free掉一块函数开始malloc的内存,goto一直都是一个比较简便的方法:
int foo()
{
    somestruct* ptr = malloc(...);
 
    dosomething...;
    if(error)
    {
        goto END;
    }
 
    dosomething...;
    if(error)
    {
        goto END;
    }
    dosomething...;
 
END:
    free(ptr);
    return 0;
 
}

由于goto不符合软件工程的结构化,而且有可能使得代码难懂,所以很多人都不倡导使用,那这个时候就可以用do{}while(0)来进行统一的管理:
int foo()
{
 
    somestruct* ptr = malloc(...);
 
    do{
        dosomething...;
        if(error)
        {
            break;
        }
 
        dosomething...;
        if(error)
        {
            break;
        }
        dosomething...;
    }while(0);
 
    free(ptr);
    return 0;
 
}

这里将函数主体使用do()while(0)包含起来,使用break来代替goto,后续的处理工作在while之后,就能够达到同样的效果。

3、避免空宏引起的warning

内核中由于不同架构的限制,很多时候会用到空宏,在编译的时候,空宏会给出warning,为了避免这样的warning,就可以使用do{}while(0)来定义空宏:

#define EMPTYMICRO do{}while(0)

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

当你的功能很复杂,变量很多你又不愿意增加一个函数的时候,使用do{}while(0);,将你的代码写在里面,里面可以定义变量而不用考虑变量名会同函数之前或者之后的重复。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,while循环语句是一种常见的循环控制结构,用于重复执行一段代码,直到指定的条件不再满足为止。while循环语句的基本语法如下所示: ``` while (condition) { // 循环体代码 } ``` 其中,`condition`是一个布尔表达式,表示循环条件。只要`condition`的值为`true`,就会重复执行循环体代码。当`condition`的值为`false`时,循环就会终止。 下面是一个简单的示例,演示了如何使用while循环语句来计算1到10的整数之和: ``` int sum = 0; int i = 1; while (i <= 10) { sum += i; i++; } System.out.println("1到10的整数之和是:" + sum); ``` 上面的代码中,`sum`变量用于存储1到10的整数之和。`i`变量用于控制循环次数,初始值为1。在每次循环中,先将`i`加到`sum`中,然后将`i`的值加1,直到`i`的值大于10为止。 另外,Java中还有一种类似的循环语句叫做do...while循环语句。它的语法与while循环语句有所不同,具体如下: ``` do { // 循环体代码 } while (condition); ``` do...while循环语句先会执行一次循环体代码,然后再判断循环条件是否满足。只要循环条件满足,就会继续执行循环体代码,直到循环条件不再满足为止。 下面是一个简单的示例,演示了如何使用do...while循环语句来输入一个整数,直到输入的值为0为止: ``` Scanner scanner = new Scanner(System.in); int num; do { System.out.print("请输入一个整数(输入0结束):"); num = scanner.nextInt(); } while (num != 0); System.out.println("输入结束。"); ``` 上面的代码中,使用Scanner类从控制台读取整数,然后使用do...while循环语句判断输入的值是否为0。只要输入的值不为0,就会继续输入,直到输入的值为0为止。最后输出“输入结束”。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值