C言語でdo.while(0)用法小結

5073 ワード

linuxカーネルコードではdoがよく見られます...while(0)のマクロ、do...while(0)は多くの役割を果たしており、以下にいくつか挙げます.
1、goto文を避ける:
通常、関数がリソースの割り当てを開始し、途中でエラーが発生した場合は関数を終了します.もちろん、終了前にリソースを解放するコードは次のようになります.
#defien N 10

bool Execute()
{
   //     
   int *p = (int *)malloc(N * sizeof(int));
   bool bOk = true;

   //          
   bOk = func1();
   if(!bOk) 
   {
      free(p);   
      p = NULL;
      return false;
   }

   bOk = func2();
   if(!bOk) 
   {
      free(p);   
      p = NULL;
      return false;
   }

   bOk = func3();
   if(!bOk) 
   {
      free(p);    
      p = NULL;
      return false;
   }

   // ..........

   //     ,       
    free(p);   
    p = NULL;
    return true;
}

ここで最大の問題はコード冗長性であり、1つの操作を増やすたびに、対応するエラー処理をしなければならず、非常に柔軟ではないので、考えたgoto:
#defien N 10

bool Execute()
{
   //     
   int *p = (int *)malloc(N * sizeof(int));
   bool bOk = true;

   //          
   bOk = func1();
   if(!bOk) goto errorhandle;

   bOk = func2();
   if(!bOk) goto errorhandle;

   bOk = func3();
   if(!bOk) goto errorhandle;

   // ..........

   //     ,       
    free(p);   
    p = NULL;
    return true;

    errorhandle:
    free(p);   
    p = NULL;
    return false; 
}

コード冗長は解決しましたが、C言語の微妙なgoto文を導入し、goto文を正しく使うことでプログラムの柔軟性と簡潔性を大幅に向上させることができますが、私たちのプログラムをつかめません.goto文の使用を避けるとともに、コード冗長性を解消するために、次のdoを使用することを考慮することができます.while(0):
#defien N 10

bool Execute()
{
    //    
    int *p = (int *)malloc(N * sizeof(int));
    bool bOK = true;


    do {
        //         
        bOK = fun1();
        if(!bOK) break;

        bOK = fun2();
        if(!bOK) break;

        bOK = fun3();
        if(!bOK) break;

        //.........
    }  while(0);

    //    
    
    free(p);
    p = NULL;
    return bOK;
}

2、空の宣言がコンパイル時に警告することを避ける:
linuxカーネルソースコードでは、コンパイル時に警告が表示されないようにするマクロがよく見られます.
#define FOO do { } while(0)

3、慣習に合ったコードブロックを作成する:
次のマクロをよく使うかもしれません.
#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }

しかし、場合によっては失効し、次のコードはifを使用します.else...
if (x > y)
        exch(x,y);          //    1
else  
        do_something();     //    2

ただし、ブランチのif文として解釈されます.
if (x > y) {     
        int tmp;            
        tmp = x;            
        x = y;
        y = tmp;
}
;                           //    
else                        // ERROR!!! 
        do_something();

エラーは";"にあります.コードブロックの後ろに直接位置し、解決策はコードをdoに埋め込むことです.while(0)では、次のコードが得られます.
if (x > y)
        do {
                int tmp;
                tmp = x;
                x = y;
                y = tmp;
        } while(0);
else
        do_something();

上のマクロは次のように変更できます.
#define exch(x,y)       do {\
                int tmp;\
                tmp = x;\
                x = y;\
                y = tmp;\
        } while(0)

4、条件文で複雑なマクロを使用する:
マクロに次のようなコードが含まれている場合:
#define FOO(x) \
        printf("arg is %s
", x); \ do_something_useful(x);

次のコードを想像してみましょう.
if (blah == 2)
        FOO(blah);

次のように解釈されます.
if (blah == 2)
        printf("arg is %s
", blah); do_something_useful(blah);;

if文はprintf(),do_にのみ作用することが分かった.something_useful()は、ifコードに予想通りに含まれていないため、希望通りに実行されません.したがって、次のコードブロックを使用できます.
if (blah == 2)
        do {
                printf("arg is %s
", blah); do_something_useful(blah); } while (0);

これにより、上記のマクロを次のように変更できます.
#define  FOO(x) do { \
                 printf("arg is %s
", blah);\ do_something_useful(blah);\ } while (0)

 
 
 
 
 
 
記事ソース:http://www.itnose.net/detail/6024252.htmlより多くの記事:http://www.itnose.net/type/54.html