[解決済み] マクロで無意味なdo-while文やif-else文を使っているのはなぜですか?
質問
多くのC/C++マクロで、マクロのコードが無意味な
do while
のループになります。 以下はその例です。
#define FOO(X) do { f(X); g(X); } while (0)
#define FOO(X) if (1) { f(X); g(X); } else
が何なのかがわからない。
do while
は何をしているのでしょうか? なぜ、それをしないで書かないのですか?
#define FOO(X) f(X); g(X)
解決方法は?
その
do ... while
と
if ... else
があるのは
マクロの後のセミコロンは、常に同じ意味を持ちます。 例えば
のように、2つ目のマクロがありました。
#define BAR(X) f(x); g(x)
ここで、もしあなたが
BAR(X);
の中に
if ... else
文の本文が中括弧で囲まれていない場合、あなたは悪い驚きを感じるでしょう。
if (corge)
BAR(corge);
else
gralt();
上記のコードは、次のように展開されます。
if (corge)
f(corge); g(corge);
else
gralt();
というのは、elseがもはやifに関連付けられていないため、構文的に正しくありません。 マクロの中で中括弧で囲んでも、中括弧の後のセミコロンは構文的に正しくないので、役に立ちません。
if (corge)
{f(corge); g(corge);};
else
gralt();
この問題を解決するには、2つの方法があります。 1 つ目は、カンマを使用してマクロ内のステートメントを連続させ、式のように動作する能力を失わせない方法です。
#define BAR(X) f(X), g(X)
上記のバージョンのバー
BAR
は、上記のコードを次のように展開し、構文的に正しいものにします。
if (corge)
f(corge), g(corge);
else
gralt();
の代わりに
f(X)
のように、独自のブロックに入れる必要がある複雑なコードがある場合、例えばローカル変数を宣言する場合などです。 最も一般的なケースでは、次のようなものを使用します。
do ... while
を使用すると、マクロは混乱することなくセミコロンを取る単一のステートメントになります。
#define BAR(X) do { \
int i = f(X); \
if (i > 4) g(i); \
} while (0)
を使用する必要はありません。
do ... while
で何か作ることができます。
if ... else
を使用した場合にも、同様に
if ... else
の中で展開されます。
if ... else
につながり、"
ダングリング else
"のように、既存のdangling elseの問題をさらに見つけにくくする可能性があります。
if (corge)
if (1) { f(corge); g(corge); } else;
else
gralt();
ポイントは、ダングリングセミコロンが誤りである文脈で、セミコロンを使い切ることです。 もちろん、この時点では、セミコロンを使わずに
BAR
をマクロではなく、実際の関数として使用します。
まとめると
do ... while
は、C言語プリプロセッサの欠点を回避するために存在します。 C言語のスタイルガイドで、C言語のプリプロセッサは使わないようにと書かれているのは、このようなことを心配してのことなのです。
関連
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] C++で仮想関数が必要な理由とは?
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
-
[解決済み】なぜC++プログラマは'new'の使用を最小限に抑えなければならないのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] do { ... } while (0) - 何のために良いですか?[重複]する
-
[解決済み】Cの複数行マクロ:do/while(0) vs スコープブロック [重複]。