2012-02-29 22 views
13

可能性の重複:私は以下のようなコードを満たさ
Why are there sometimes meaningless do/while and if/else statements in C/C++ macros?なぜマクロ定義でdo()while(0)を使うのですか?

#define ev_io_init(ev,cb,fd,events) \ 
do { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} while (0) 

私は著者がここにdo { } while (0)を使う理由を知りたいです。 これに違いはありますか?

#define ev_io_init(ev,cb,fd,events) { \ 
    ev_init ((ev), (cb)); \ 
    ev_io_set ((ev),(fd),(events)); \ 
} 

ところで:コードがlibevはからで、ev_local.h

答えて

10

do{}while(0)はあなたがループから分割することができます:

do{ 
    expr1; 
    foo(); 
    if (cond) 
     break; 
    expr2; 
    goo(); 
} while (0); 

それはあなたのことを除いて、簡単なブロック{...}と同じですbreakステートメントで実行を中断できます。複雑なチェックが複数ある場合を除き、単純なコードブロックではできません。 while(0)のため、まだ1回実行されます。

+8

...それがないが、しないでください... – moonshadow

+0

それがあれば、他のネストの数を減らします。 – shuva

15

ループでコードを囲むことにより、if-else-constructを "破棄"せずにプリプロセッサディレクティブが複数のステートメントを実行できるようになります。次のことを考えてみましょう:

#define DO_SOMETHING() a();b();c(); 

void foo() 
{ 
    // This is ok... 
    DO_SOMETHING(); 
} 

void bar() 
{ 
    // ...whereas this would trigger an error. 
    if (condition) 
     DO_SOMETHING(); 
    else 
     blah(); 
} 

3つの文がelse句が続いているため、2番目の例は、IF-ELSE-構造を壊します。正しく置換できるように、DO_SOMETHINGの指示はdo { ... } while(0)で囲む必要があります。

+3

もちろん、もしそのような行があるならば、あなたはコードを壊すことになるでしょう。 – Simon

+2

@Simonしかし、1行ブロックのために裸のif else行を使用するようにlinux kernel coding style adviceをしませんか? https://www.kernel.org/doc/Documentation/CodingStyle – CoderSpinoza

+2

@CoderSpinoza明らかにそうです。もし私がLinuxカーネルで作業するなら、私はそのスタイルに従います。他の場所では、私はそれを避けるだろう。 – Simon

23

function1()が実際にマクロであれば、単に{ }を使用すると、使用時にセミコロンを省略することが必要ですが、do { } while(0)はあなたが本当の機能とまったく同じ構文を使用することができますif(something) function1(); else function2();

を考えてみましょう。

(すべてでブロック構築物のいずれかの種類を使用していないことがちょうど完全に壊れたコードを生成し、natch)

関連する問題