web-dev-qa-db-ja.com

マクロを定義するときにdo while(0)を使用するとどうなりますか?

可能性のある複製:
C/C++マクロのDo-Whileおよびif-elseステートメント

Linuxカーネルを読んでいると、次のような多くのマクロが見つかりました。

#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

単に{}で定義するのではなく、なぜこれを使用するのですか?

124
amazingjxq

これにセミコロンを付けて、関数のように見せて動作させることができます。また、if/else節でも適切に機能します。

While(0)がなければ、上記のコードは

if (doit) 
   INIT_LIST_HEAD(x);
 else 
   displayError(x);

マクロの後のセミコロンはelse節を「食べる」ため、上記はコンパイルさえできません。

138
SPWorley

複数のステートメントを1つのマクロにグループ化できます。

次のようなことをしたと仮定します。

if (foo) 
    INIT_LIST_HEAD(bar);

マクロがカプセル化do {...} while(0);なしで定義された場合、上記のコードは次のように展開されます。

if (foo)
    (bar)->next = (bar);
    (bar)->prev = (bar);

Fooが保持される場合、最初のステートメントのみが実行されるため、これは明らかに意図したものではありません。 2番目のステートメントは、fooが保持されているかどうかに関係なく実行されます。

編集: http://c-faq.com/cpp/multistmt.html および http://developer.Apple.com/documentation/DeveloperTools/gcc-4.0。 1/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon

42
rodion