可能な重複:
マクロを定義するときにdo while(0)を使用するとどうなりますか?
C/C++マクロにdo/whileおよびif/elseステートメントが無意味になることがあるのはなぜですか?
{…} while(0)それは何のためですか?
Do/while(0)ループ内にラップされた複数行のCマクロを見ました:
#define FOO\ do {\ do_stuff_here\ do_more_stuff\ } while(0)
基本的なブロックを使用するのではなく、そのようにコードを書くことの利点は(もしあれば):
#define FOO\ {\ do_stuff_here\ do_more_stuff\ }
http://bytes.com/groups/c/219859-do-while-0-macro-substitutions
アンドレイ・タラセビッチ:
「do/while」バージョンを使用するという考えは、複合ステートメントではなく通常のステートメントに展開されるマクロを作成することです。これは、すべてのコンテキストで通常の関数を使用して、関数スタイルマクロの使用を統一するために行われます。
次のコードスケッチを検討してください
if (<condition>)
foo(a);
else
bar(a);
ここで、「foo」と「bar」は通常の関数です。ここで、関数「foo」を上記の性質のマクロに置き換えたいと想像してください。
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
マクロが2番目のアプローチ(「{」と「}」のみ)に従って定義されている場合、「if」の「true」ブランチが複合ステートメントで表されるため、コードはコンパイルされなくなります。そして、「;」を入れるとこの複合ステートメントの後、「if」ステートメント全体を終了し、「else」ブランチを孤立させます(コンパイルエラーが発生します)。
この問題を修正する1つの方法は、「;」を入れないことを覚えておくことです。マクロ「呼び出し」の後
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
これは期待どおりにコンパイルおよび動作しますが、これは均一ではありません。よりエレガントな解決策は、マクロが複合ステートメントではなく、通常のステートメントに展開されるようにすることです。これを達成する1つの方法は、次のようにマクロを定義することです
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
今、このコード
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
問題なくコンパイルされます。
ただし、CALL_FUNCS
の私の定義とメッセージの最初のバージョンとの小さなながらも重要な違いに注意してください。 } while (0)
の後に;
を付けませんでした。 ;
をその定義の最後に置くと、 'do/while'を使用するポイント全体がすぐに無効になり、そのマクロは複合ステートメントバージョンとほぼ同等になります。
元のメッセージで引用したコードの作者がwhile (0)
の後にこの;
を置いた理由がわかりません。この形式では、両方のバリアントが同等です。 'do/while'バージョンを使用する背後にある全体のアイデアは、この最後の;
をマクロに含めないことです(上記で説明した理由のため)。