C言語におけるswitch文の落とし穴

注意: この記事は1年以上前に掲載されたものです。情報が古い場合がありますのでお気を付け下さい。

C言語におけるswitch文の扱いは要注意である。これを想定して書いたつもりが、実際にはありえないことになってしまうこともあるからである。

落とし穴の実例

以下のコードがあったとする。

#include <stdio.h>
#include <stdlib.h>

int main(const int argc, const char *argv[])
{
    if (argc != 0) {
        return EXIT_FAILURE;
    }
    int num = atoi(argv[1]);
    switch (num) {
    case 0:
        puts("0");
    case 1:
        puts("1");
    case 2:
        puts("2");
    default:
        puts("default");
    }
    return EXIT_SUCCESS;
}

上記のコードをswitch.cとして保存し、switch ((Windowsではswitch.exe)) としてコンパイルを行った後、以下のコマンドを入れたら何が出力されるだろうか?

./switch 1

答え

1
2
default

解説

C言語においては、switch文は、あるケースを満たした場合の部分から処理を開始する性質があるが、困ったことに、breakを明示的に入れないと、その次のcaseの処理も行なってしまうという問題をはらんでいる。

例えば、上記のコマンドを入れた場合は、case 1を満たしているので、その処理を開始した後、そこからブロックを抜けることがなく、case 2defaultの処理まで行ってしまうのである。

これは、見落としてしまって問題となるので、要注意である。

対処法

この場合、基本的には以下の例外を除いてはあるcaseの最後の部分には必ずbreakを入れるようにすることで対処が可能である。こうすれば、次のcaseに進むことはない。例えば、以下のようにする。

#include <stdio.h>
#include <stdlib.h>

int main(const int argc, const char *argv[])
{
    if (argc != 0) {
        return EXIT_FAILURE;
    }
    int num = atoi(argv[1]);
    switch (num) {
    case 0:
        puts("0");
        break;
    case 1:
        puts("1");
        break;
    case 2:
        puts("2");
        break;
    default:
        puts("default");
        break;
    }
    return EXIT_SUCCESS;
}

上記のようにすれば、基本的には問題ない。

例外

例外として、あるcase文の後にその下のケースの処理を行いたい場合は、breakを加えなければいいだけなのだが、その場合、問題を起こすことがあるため、明示的にコメントを入れたほうが良い。例えば、case 1の場合はcase 2の処理も行いたいという場合は、以下のようにする。

#include <stdio.h>
#include <stdlib.h>

int main(const int argc, const char *argv[])
{
    if (argc != 0) {
        return EXIT_FAILURE;
    }
    int num = atoi(argv[1]);
    switch (num) {
    case 0:
        puts("0");
        break;
    case 1:
        puts("1");
        // FALLTHROUGH
    case 2:
        puts("2");
        break;
    default:
        puts("default");
        break;
    }
    return EXIT_SUCCESS;
}

上記の場合は、case 1の最後の部分に意図的にFALLTHROUGHというコメントを入れることで、明示的にフォールスルーを行っていることを示すことができる。コード自体は特に意味をなしていないのだが、意図的にフォールスルーを行っているということを判断する重要な材料になる。

最後に

C言語のSwitch文は気づかないうちに問題を起こすことがあるので、しっかりと気をつけたほうが良いだろう。自由度は高いものの、こういうミスでバグが発生するということは念頭に入れたいものである。

タイトルとURLをコピーしました