zoukankan      html  css  js  c++  java
  • 嵌入式编程中使用 do{...} while(0) 的解释

    最近在看esp32的idf,有一些宏定义使用了do while(0)这种看起来好像没啥用的代码。然后我查了一下资料,发现在linux内核代码中经常用到这个东西!

    现在就将这个东西整理一下。

            

    为什么在内核中碰到很多  

    #define ...  do{...} while(0) 

    有以下几点原因:

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

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

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

    #define FOO(x) 
    
         printf("arg is %s
    ", x); 
    
         do_something_useful(x);

    如果这样用:

        if (blah == 2)    F00(blah);

    将会被展开为:

      if (blah == 2)
    
                  printf("arg is %s
    ", blah);
    
                  do_something_useful(blah);

     这样,if条件之后包含了printf()语句,而do_something_useful()调用不能按照预期那样工作。

    而用do {...} while(0)定义后,就会展开成以下语句:   

    if (blah == 2)
    
    do{
    
                  printf("arg is %s
    ", 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)  do_something();  

    现在在程序中这样使用这个宏:  

    if(temp)  
                 macro(i);  
    else  
                 do_anotherthing();  

    一切看起来很正常,但是仔细想想。这个宏会展开成:  

    if(temp)  
                 if(condition)  do_something();  
    else    
                 do_anotherthing();  

    这时的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

  • 相关阅读:
    笔记-归并排序
    Repeated Substring Pattern
    Assign Cookies
    Number of Boomerangs
    Paint Fence
    Path Sum III
    Valid Word Square
    Sum of Two Integers
    Find All Numbers Disappeared in an Array
    First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/nevel/p/6296303.html
Copyright © 2011-2022 走看看