linux中do while(0)的解释

        在看ldlm的代码过程中遇到了一个很奇怪的问题,有很多宏定义使用了do while(0)这种看起来好像没啥用的代码。然后我就问问师兄,才得知,这种用法很常见,自己又查了一下资料,原来在linux内核代码中经常用到这个东西!现在就将这个东西整理一下。

        

为什么在内核中碰到很多  #define ...  do{...} while(0) ?

有以下几点原因:

1、空语句在编译的时候会出现警告,所以有必要用#define FOO do{ } while(0)

2、给定一个基本块,可以在里面定义局部变量

3、为了能够在条件语句中使用复杂的宏定义。例如下面这段代码:

     #define FOO(x) \

     printf("arg is %s\n", x); \

     do_something_useful(x);

      如果这样用:

      if (blah == 2)

          F00(blah);

      将会被展开为:

      if (blah == 2)

              printf("arg is %s\n", blah);

              do_something_useful(blah);

       这样,if条件之后包含了printf()语句,而do_something_useful()调用不能按照预期那样工作。而是用do {...} while(0)定义后,就会展开成以下语句:   

if (blah == 2)

do{

              printf("arg is %s\n", blah);

              do_something_useful(blah);

}while(0);

这是我们所期望的。

如果你希望定义一个包含多行语句和一些局部变量的时候. 一般的定义方式只能这样:

  #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

  然而在某些情况下,这样并不能正常工作. 下面是包含两个分支的if语句:

  if (x > y)

  exch(x,y);          // Branch 1

  else

  do_something();     // Branch 2

  但这样却只能展开成单分支的if语句,如下:

  if (x > y) {                // 单分支if

  int tmp;

  tmp = x;

  x = y;

  y = tmp;

  }

  ;                           // 空语句

  else                        // 错误!!! "parse error before else"

  do_something();

  问题是由于在语句块后直接加入分号(;)引起的. 解决办法是将语句块放入 do 和 while (0)中间.这样就得到了一条单语句, 而不是被编译器判断为语句块.现在的if语句如下:

  if (x > y)

  do {

  int tmp;

  tmp = x;

  x = y;

  y = tmp;

  } while(0);

  else

  do_something();



假设有这样一个宏定义  
 
#define  macro(condition)  if(condition)  dosomething();  
 
现在在程序中这样使用这个宏:  

if(temp)  
             macro(i);  
else  
             doanotherthing();  
 
一切看起来很正常,但是仔细想想。这个宏会展开成:  
 
if(temp)  
             if(condition)  dosomething();  
else    
             doanotherthing();  
 
这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。  
 
为了避免这个错误,我们使用do{….}while(0)  把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。  


参考资料

http://blog.csdn.net/chenhu_doc/article/details/856468

http://www.233.com/linux/fudao/20101102/140715235.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: while do是Linux的一个循环语句,用于重复执行一段代码,直到指定的条件不再满足为止。while do的基本语法如下: while [ condition ] do command1 command2 ... done 其,condition是一个条件表达式,如果该表达式的值为真,则执行do的命令,否则跳出循环。command1、command2等是需要重复执行的命令。 在while do循环,可以使用break和continue语句来控制循环的执行流程。break语句用于跳出整个循环,而continue语句则用于跳过当前循环,继续执行下一次循环。 总之,while do是Linux非常常用的一个循环语句,可以帮助我们简化代码,提高效率。 ### 回答2: 在Linux,while do是一种循环结构,用于重复执行一组操作,直到满足特定条件为止。 while do的语法形式为: ``` while condition do statements done ``` 其,condition为循环条件,通常是一个比较表达式,如变量的值是否满足某个条件。只要条件为真,即非零值,循环将一直执行。一旦条件为假,循环将停止执行。 do和done之间的statements是需要重复执行的操作,可以是任意数量的命令或命令序列。statements的每个命令都应该以分号结尾(除了最后一个命令)。可以使用大括号{}将多个命令组合在一起作为单个命令。 在每次循环开始时,循环条件将被重新评估。如果条件为真,则继续执行statements。一旦条件为假,则跳出循环,执行循环后的下一条语句。 在循环体内部,可以使用break语句来立即跳出循环,或使用continue语句跳过本次循环的剩余部分,直接进入下一次循环。 总之,while do结构提供了一种简便的方式来实现对一组操作的重复执行,直到满足特定的条件。它可以用于各种不同的场景,例如处理文件,计算数学表达式等。 ### 回答3: 在Linux,while do是一种用于循环执行一系列命令的语法结构。 while do的用法如下: while [ condition ] do command1 command2 ... commandN done 其,condition是一个条件表达式,如果条件表达式为真,则会执行循环块的命令,否则跳出循环。 command1到commandN是要执行的命令,可以是任意的合法Linux命令。 循环的执行流程如下: 1. 首先,条件表达式会被计算,如果为真,则执行循环块的命令,否则直接退出循环。 2. 执行循环块的命令,按照从上到下的顺序执行。 3. 执行完循环块的所有命令后,再次计算条件表达式,如果为真,则继续执行循环块的命令,否则退出循环。 4. 重复执行步骤2和步骤3,直到条件表达式为假时,循环结束。 在实际使用,循环块的命令可以用于做重复性的任务,比如遍历文件或目录、读取文件内容、计算数据等等。可以灵活地根据具体需求编写循环块的命令,从而实现更复杂的逻辑。 总而言之,while do是Linux用于循环执行一系列命令的语法结构,通过判断条件表达式的真假,来控制循环块命令的执行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值