よくマクロでdo{ ... }while(0);
という書き方がされている。単にスコープを作るだけなら{ ... }
のほうが見やすいと思う。しかし、do{ ... }while(0);
と{ ... }
は違う。
何が違うって、do{ ... }while(0);
はあくまでもループなので、continue;
やbreak;
の抜け先が異なるのだ。
展開された状態で
for(i=0; i<100; i++){ do{ printf("Hello, World %d\n", i); if(i==10) break; }while(0); }
は100回ループを回るが、
for(i=0; i<100; i++){ { printf("Hello, World %d\n", i); if(i==10) break; } }
は10までしか表示されない。どちらが望ましいかはケースによって異なる。この違いを認識しないでいろいろなマクロを書いていると、わけがわからないバグとしていつか表面に現れるだろう…っていうか、実際に(もうちょっと複雑なケースで)バグったから書いてるんだけど(笑)。
実際にバグったのを説明すると、リストをたどる用のマクロ(foreach〜forendで囲むタイプのもの)というのを使ってて、do{ ... }while(0);
じゃなくて{ ... }
を使っていた。で、次の要素に移るとか、forendのほうでもちょっと処理していた。で、ループの中でcontinueを書いてもcontinueになってなかったのだ。forend側の}
の前に書いてあった、いわゆるi=i->next;
の処理が実行されない。do{ ... }while(0); i=i->next;
のようにcontinueで飛びたい部分を囲むとよい。ただこれじゃ、break
で抜けられなくなっちゃうのだけどね。要はcontinueとbreakのどちらを取るかって話だが、for文を使ってi=i->next
な部分をforに押し込めるのが正しいと思う。あるいはbreakとcontinueだとbreakのほうが使うから、continueを禁止するか。