内核代码宏中 do{...}while(0) 的作用

3017阅读 0评论2012-06-11 luotaijia
分类:LINUX

    在内核空间非常有限的情况下,为什么还要在某些宏里增加 do{...}while(0) 这种“没用”的代码行呢?

    带参数的宏定义的一般形式为:   
             #define   <宏名>(<参数表>)    <宏体>
    <宏名>:一个标识符
    <参数表>:参数可以是一个或多个。多个参数之间用逗号分隔
    <宏体>:被替换用的字符串,字符串是由参数表中的各个参数组成的一个或多个表达式
    *宏体在调用处直接展开
     eg:#define  N  2+3
            int main ()
            {
                  int n;
                  n = N*2;
                  printf ("%d", n);
                  return 0;
            }
           答案为8 (2+3*2=8)

  假设有这样一个宏定义:
              #define exch(x,y) int tmp; tmp=x; x=y; y=tmp;

   当我们这样用的时候:
             if (x > y) 
                exch(x,y);     
          else 
               do_something();        
   根据宏的用法,可得:
          if (x > y) 
               int tmp; 
               tmp = x;
               x = y; 
               y = tmp; 
          ;                            // empty statement 
         else 
              do_something();
   此时,语句tem = x; x = y; y = tmp;明显不在if代码块内。 


如果直接在宏定义处加上{},即:
        #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

那确实是解决了上面的问题,可是还会出现新的问题:
       if (x > y)
       { 
             int tmp; 
             tmp = x; 
             x = y;
             y = tmp;
       };                            // empty statement
       else 
            do_something();

  error: ‘else’ without a previous ‘if’
  else 前面的 ;表明之前已经是一个(段)完整的语句了,那么接下来直接用 else 就有语法错误了

 但是用上 do{...}while(0) 之后:
        if (x > y) 
             do { 
                     int tmp;
                     tmp = x; 
                     x = y; 
                     y = tmp; 
                  } while(0); 
        else 
                   do_something();


  为了尽量避免错误,使用do{….}while(0)  把代码块包裹起来,成为一个独立的语法单元,从而不会与上下文发生混   淆。绝大多数的编译器都能够识别do{…}while(0)并进行优化,所以使用这种方法也不会导致程序的性能降低。



参考资料:

 
上一篇:Linux内核中链表的实现与应用
下一篇:存储芯片的扩展