C言語でプログラムを書いていると一度はwhile(0)という文を見たことがあるだろう。クロックのカラ消費ぐらいにしか意味がないと思われるこの文も、マクロ中では意味を持つ。下記のコードをご覧いただきたい。
#include <iostream> #define PRINT1(str) { std::cout << str << std::endl; } #define PRINT2(str) do { std::cout << str << std::endl; } while(0) int main(void) { PRINT1("Hello world with semicolon."); PRINT1("Hello world without semicolon.") // 両方OK PRINT2("Hello world with semicolon."); // PRINT2("Hello world without semicolon.") // COMPILE ERROR! return 0; }
このように、マクロの後ろに確実にセミコロンをつけさせたいときにdo while(0)は使われる。マクロの作者は普通の関数と同様にふるまわせたいと思ったのだろう。あるいは、セミコロンが不揃いだとIDEのオートインデントが誤判定するので鬱陶しく思ったのかもしれない。
しかしながら、なんでもかんでもdo while(0)で囲むのは考え物だ。筆者はマクロの高度な使いこなしはアンチパターンに近いものだと考えており、このテクニックに対しても良い印象は持っていない。なぜ?と思う方は、doを消して文末のセミコロンをつけたり消したりしてビルドしてみてほしい。セミコロンがない場合に、マクロの次の行が黙って実行されなくなるという、非常に使用者を混乱させる振る舞いとなることがお分かりいただけると思う。doをつけ忘れないという保証はできないし、静解析でも発見しづらいのでやはり多用は避けた方が良い。do while(0)は見た時に意図が理解できる程度にとどめておくのが無難だ。
コメント