ぶら下がりelse問題とは


ぶら下がりelse

ぶら下がりelse(Dangling else)は、特定のif文に紐付くよう意図されていたelse文が、書き手の意図に反して異なる別のif文に紐付いてしまっている状態のことを言う。この状態によって引き起こされる問題は宙ぶらりんelse問題(dangling else problem)とも呼ばれている。人によってはdangling elseをダングリングポインタよろしく「ダングリングelse」と呼ぶこともあるため覚えておきたい。

ぶら下がりelseの問題は、フリーフォーマットやブレース省略の仕組みを採用したC言語やJava, PHP, Perl, JavaScript等の言語で発生しやすい。オフサイドルールを採用して字下げのレベルに意味を持たせたPythonやCofeeScript等の言語ではこの問題は起こらない。またブレースの記述を必須とするSwiftやGo等の言語も同様にこの問題は起こらない。

目次

スポンサーリンク

ぶら下がりelseの例

例えば、以下のelse文はif (!a)文に対応するelse文と思われるかもしれないが、実際にはif (b)文に紐付いたelse文と解釈されてしまう。

ぶら下がりelse状態の危険なコード

if (!a)
    if (b)
        b();
else
    a();

プログラミング言語側の解釈

書き手の意図に反してプログラミング言語側ではこちらの解釈が行われてしまう。

if (!a)
    if (b)
        b();
    else
        a();

このように、プログラムの書き手とプログラミング言語側で異なる解釈が生まれてしまうという厄介さがある。

以下のコードは両者の解釈の違いをブレースを用いて表現したものである。

/* 書き手が意図していた解釈 */
if (!a) {
    if (b)
        b();
} else {
    a();
}

/* プログラミング言語側の解釈 */
if (!a) {
    if (b)
        b();
    else
        a();
}

ぶら下がりelse問題の対処

if文ネスト時には、ブレース(波括弧)を適切に用いてブロック間の関係を明示する。これで ぶら下がりelse問題を回避できる。

if (!a) {
    if (b)
        b();
} else
    a();

理想はブレースの省略を行わないことである。この書き方なら ぶら下がりelseの問題は発生しない。

if (!a) {
    if (b) {
        b();
    }
} else {
    a();
}

どうしてもブレース省略を活用したい場合には、「外側のブロックではブレースの明示を必須とする」というコーディング規約を採用するとよい。

if (!a) {
    if (b)
        b();
    else
        c();
} else {
    a();
}

ただ、安全性を重視する現代のシステム開発では、ブレースの省略はあまり好まれないため注意して利用されたい。

ぶら下がりelseへの警告

現代のコンパイラは ぶら下がりelseを事前に警告してくれることがある。

if (!a)
    if (b)
        b();
else // 警告: Add explicit braces to avoid dangling else
    a();
このように ぶら下がりelseを回避するための明示的なカッコを追加するよう促される。

ただし、インタプリタ言語では依然警告されないものも多くあるため、ぶら下がりelse問題には引き続き注意しなければならない。

広告