Andrey Tarasevich は、次の説明を提供します。
- Google グループで
- bytes.com で
【書式を一部変更しました。角括弧内に追加された括弧内の注釈[]
]。
「do/while」バージョンを使用する全体的なアイデアは、複合ステートメントではなく、通常のステートメントに展開されるマクロを作成することです。これは、関数スタイルのマクロの使用を、すべてのコンテキストで通常の関数の使用と統一するために行われます。
次のコード スケッチを検討してください。
if (<condition>)
foo(a);
else
bar(a);
ここでfoo
とbar
は通常の関数です。ここで、 function を上記の性質 [named ]foo
のマクロに置き換えたいと想像してください:CALL_FUNCS
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
{
ここで、マクロが 2 番目のアプローチ ( andのみ)に従って定義されている場合}
、コードはコンパイルされなくなりますif
。そして、;
この複合ステートメントの後に a を配置すると、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)
。その定義の最後にa;
を配置すると、'do/while' を使用するポイント全体が即座に無効になり、そのマクロは複合ステートメント バージョンとほぼ同等になります。
;
元のメッセージで引用したコードの作成者が、これを の後に置いた理由がわかりませんwhile (0)
。この形式では、両方のバリアントが同等です。「do/while」バージョンを使用する背後にある全体的な考え方は、この final;
をマクロに含めないことです (上記で説明した理由により)。