C言語のswitch-caseで「1の場合」「2の場合」「それ以外」を分岐する方法|基本構文・break・default解説

条件分岐を読みやすく整理したいときに便利なのがC言語のswitch-case構文です。

特に「1の場合」「2の場合」「それ以外」のように離散的な値で分けたい場面で有効です。

本稿では基本構文からbreakとフォールスルー、defaultの扱い、複数条件のまとめ方、型やスコープの注意点、ループ内での挙動まで、実用的なコツを交えて解説します。

基本構文

switchは整数系の値に応じて分岐する構文

switchは式の評価結果(整数型)に応じて、該当するcaseラベルの位置から処理を開始します。

該当するcaseがないときはdefaultが実行されます。

caseブロックは明示的にbreakしない限り、次のcaseへ処理が落ちていく(フォールスルー)点がif-elseとの大きな違いです。

基本の書き方

最も基本的な形は次のとおりです。

各caseの末尾でbreakしてswitch文を終了させるのが通常の書き方です。

C言語
// 基本構文イメージ(テンプレート)
switch (expr) {
  case 1:
    // 1に一致したときの処理
    break;          // switchを抜ける
  case 2:
    // 2に一致したときの処理
    break;
  default:
    // どのcaseにも当てはまらないとき
    break;
}

ポイント

  • switchに与えるexprは整数型(int, char, enum, long など)。浮動小数点(float, double)は不可です。
  • caseラベルは「整数定数式」でなければなりません。重複はコンパイルエラーになります。
  • 通常は各caseでbreakします。省くと次のcaseへ“落ちる”ため、意図しないフォールスルーはバグの温床になります。

「1の場合」「2の場合」「それ以外」の具体例

動くサンプル(複数の入力例を一度に確認)

配列で複数の入力を試し、「1」「2」「それ以外」の出力をまとめて確認します。

C言語
#include <stdio.h>

int main(void) {
    int xs[] = {1, 2, 5};
    size_t n = sizeof(xs) / sizeof(xs[0]);

    for (size_t i = 0; i < n; ++i) {
        int x = xs[i];
        printf("x = %d -> ", x);

        switch (x) {
            case 1:
                puts("1の場合");
                break;
            case 2:
                puts("2の場合");
                break;
            default:
                puts("それ以外");
                break;
        }
    }
    return 0;
}
実行結果
x = 1 -> 1の場合
x = 2 -> 2の場合
x = 5 -> それ以外

breakの役割とフォールスルー

breakはそのswitch文から抜ける

breakは「そのswitch文だけ」を終了させます。

外側にループがあっても、そのループは抜けません。

breakを省くと次のcaseへ処理が落ちる(フォールスルー)

breakを省略すると、該当caseの後に続くcaseの処理も実行されます。

これをフォールスルーと呼びます。

意図する場合もありますが、意図しないフォールスルーはバグの原因になるため注意が必要です。

C言語
#include <stdio.h>

int main(void) {
    for (int x = 1; x <= 2; ++x) {
        printf("x = %d:\n", x);
        switch (x) {
            case 1:
                puts("Aの処理");
                /* フォールスルー: 次のcaseへ意図的に落とす */
                /* 一部のコンパイラでは以下のようなコメントで警告抑止が可能
                   // fall through
                */
            case 2:
                puts("Bの処理");
                break;
            default:
                puts("defaultの処理");
                break;
        }
    }
    return 0;
}
実行結果
x = 1:
Aの処理
Bの処理
x = 2:
Bの処理

ヒント:

  • 最近のコンパイラでは-Wimplicit-fallthrough等の警告が有効な場合、意図的なフォールスルーに注釈を付けるとよいです(コメントやコンパイラ拡張属性を使用)。

defaultの扱い

defaultは一致するcaseがないときに実行

defaultはどのcaseにも一致しなかったときに実行されます。

配置場所は文法上どこでも構いませんが、最後に置くと読みやすくなります。

defaultでも処理の最後にbreakを忘れないようにします。

C言語
#include <stdio.h>

int main(void) {
    int x = 42;

    switch (x) {
        case 1:
            puts("1");
            break;
        case 2:
            puts("2");
            break;
        default:
            puts("それ以外");
            break;
    }
    return 0;
}
実行結果
それ以外

複数条件をまとめる書き方

同じ処理はcaseを連続して書く

同じ処理にまとめたいときは、caseを並べてbreakを一つだけ書きます。

C言語
#include <stdio.h>

int main(void) {
    int xs[] = {1, 2, 3};
    size_t n = sizeof(xs) / sizeof(xs[0]);

    for (size_t i = 0; i < n; ++i) {
        int x = xs[i];
        printf("x = %d -> ", x);

        switch (x) {
            case 1:
            case 2:
                puts("1または2");
                break;
            default:
                puts("それ以外");
                break;
        }
    }
    return 0;
}
実行結果
x = 1 -> 1または2
x = 2 -> 1または2
x = 3 -> それ以外

範囲はcaseでは書けないのでifで補う

case 1 ... 5のように範囲指定は標準Cでは書けません。

必要に応じてifを併用します。

C言語
#include <stdio.h>

int main(void) {
    int xs[] = {0, 3, 7};
    size_t n = sizeof(xs) / sizeof(xs[0]);

    for (size_t i = 0; i < n; ++i) {
        int x = xs[i];
        printf("x = %d -> ", x);

        switch (x) {
            case 0:
                puts("特別扱い(0)");
                break;
            default:
                if (1 <= x && x <= 5) {
                    puts("1〜5の範囲");
                } else {
                    puts("それ以外");
                }
                break;
        }
    }
    return 0;
}
実行結果
x = 0 -> 特別扱い(0)
x = 3 -> 1〜5の範囲
x = 7 -> それ以外

型と定数のルール

使用できる式とcaseラベル

  • 式(switch (expr)expr):
    • 整数型に限られます。int, char, short, long, long long, _Boolbool)やenumが対象です。
    • 浮動小数点型(float, double, long double)は不可です。
  • caseラベル:
    • 「整数定数式」のみ。数値リテラル、enum定数、sizeofや算術からなる定数式など。
    • 同じ値の重複は不可です(コンパイルエラー)。
  • 型変換の注意:
    • charshortは整数昇格して比較されます(多くの環境でint相当)。
    • enumは可読性を上げ、caseに意味のある名前を与えられます。

enumで可読性を高める例

C言語
#include <stdio.h>

typedef enum {
    MODE_NONE = 0,
    MODE_ADD  = 1,
    MODE_SUB  = 2
} Mode;

int main(void) {
    Mode m = MODE_SUB;

    switch (m) {
        case MODE_ADD:
            puts("加算モード");
            break;
        case MODE_SUB:
            puts("減算モード");
            break;
        case MODE_NONE:
        default:
            puts("未選択");
            break;
    }
    return 0;
}
実行結果
減算モード
参考(よくある可否の早見)
  • OK: switch ((int)c) { ... }, switch (status_enum) { ... }, case 10+2: ...
  • NG: switch (3.14) { ... }, case x:(変数は不可), case 1.5:(浮動小数は不可)

変数宣言とスコープの注意

case直後に変数を初期化するならブロックで囲む

caseラベル直後に初期化を伴う宣言を書くと、制御フロー上の到達性やスコープの問題でコンパイルエラーや警告の原因になります。

ブロック{}で囲んでスコープを限定しましょう。

C言語
#include <stdio.h>

int main(void) {
    int x = 1;

    switch (x) {
        case 1: {
            int a = 10;  // ブロックスコープで安全に初期化
            printf("a = %d\n", a);
            break;
        }
        default:
            puts("default");
            break;
    }
    return 0;
}
実行結果
a = 10

補足:

  • 変数の寿命や名前の衝突を避けるためにも、ブロックで囲む習慣は有効です。

ループ内でのbreak/continue

switch内のbreakはswitchのみを抜ける

ループの内側にswitchがあるとき、switch内のbreakはループではなくswitchを終了します。

ループ自体を抜けたい場合は、フラグ変数やgotoなど別の手段が必要です。

continueはループに作用する(switchではない)

switchの中でcontinueを書くと、それは内側のswitchではなく外側のループに作用して、次の反復へ進みます。

C言語
#include <stdio.h>

int main(void) {
    for (int i = 0; i < 5; ++i) {
        switch (i) {
            case 2:
                puts("hit 2: break -> ループは続行");
                break;                  // switchのみを抜ける
            case 3:
                puts("hit 3: continue -> ループの次反復へ");
                continue;               // forループに作用
            default:
                printf("i = %d\n", i);
                break;
        }
        puts("switchを抜けた後の処理");
    }
    return 0;
}
実行結果
i = 0
switchを抜けた後の処理
i = 1
switchを抜けた後の処理
hit 2: break -> ループは続行
switchを抜けた後の処理
hit 3: continue -> ループの次反復へ
i = 4
switchを抜けた後の処理

ループごと抜けたい場合は「二重のbreak」は存在しません。

gotoでラベルへ飛ぶ、関数を分割してreturnする、条件フラグでループ終了を制御する、などの設計が必要です。

まとめ

基本は「caseごとに処理を書き、最後にbreak」「どれにも当てはまらないときのためにdefault」という型です。

同一処理はcaseを並べて集約し、範囲や複雑な条件はifを併用して表現します。

switchの式は整数型のみ、caseは整数定数式のみ。enumを活用すると可読性が上がります。

breakはswitchのみを抜け、ループ内ではcontinueがループに作用します。意図しないフォールスルーを避け、必要な場合は明示的なコメント等で意図を残しましょう。

変数宣言はブロックでスコープを限定すると安全です。これらのポイントを押さえることで、「1の場合」「2の場合」「それ以外」といった典型的な分岐を、読みやすく堅牢に書けます。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!