言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

C++辞典

  1. トップページ
  2. C++辞典
  3. switch / case

switch / case

『C++』では switch 文を使うと、整数値や列挙型の値に応じて複数の分岐先を簡潔に記述できます。if-else if の連鎖と異なり、対応する case ラベルへ直接ジャンプするため、分岐数が多い場面でも可読性が保たれます。

構文

// ========================================
// switch 文の基本構文
// ========================================

switch (式) {
    case 定数値1:
        // 式が定数値1と一致した場合に実行します
        break;
    case 定数値2:
        // 式が定数値2と一致した場合に実行します
        break;
    default:
        // どの case にも一致しなかった場合に実行します
        break;
}

// ----------------------------------------
// 初期化付き switch(C++17 以降)
// ----------------------------------------

switch (初期化式; 条件式) {
    case 定数値1:
        // 処理
        break;
    default:
        break;
}

構文一覧

構文・キーワード概要
switch (式)式を評価し、一致する case ラベルへジャンプします。式は整数型・列挙型・char 型のみ使用できます。
case 定数値:式の値と一致した場合にここから処理を開始します。定数値はコンパイル時定数でなければなりません。
default:どの case にも一致しなかった場合に実行します。省略可能ですが、記述されることが多いです。
break;switch ブロックを抜けます。省略すると次の case へ処理が流れ落ちる(fallthrough)ため、意図がない限り必ず記述します。
fallthrough(意図的)break を省略して次の case へ処理を続行させます。C++17 以降は [[fallthrough]]; 属性を付けると警告を抑制できます。
switch (初期化式; 条件式)C++17 で追加された初期化付き switch です。スコープを switch ブロック内に限定した変数を宣言できます。

サンプルコード

battle_rank.cpp
// ========================================
// battle_rank.cpp
// 龍が如くのキャラクターの戦闘ランクを判定します
// switch 文による多岐分岐のサンプルです
// ========================================

#include <iostream>
#include <string>

int main() {
    std::string fighter = "真島吾朗";  // 判定対象のファイターです

    // 戦闘ランクのレベルです
    // 0: 新人, 1: 中堅, 2: 幹部, 3: 最高幹部, 4: 組長クラス
    int rank = 2;

    std::cout << "【極道バトルランク判定】" << std::endl;
    std::cout << "ファイター: " << fighter << std::endl;

    // switch 文でランクに応じた評価を決定します
    switch (rank) {
        case 0:
            // 新入りの段階です
            std::cout << "判定: 新人 — 見習い扱いです" << std::endl;
            break;

        case 1:
            // 実力が認められはじめた段階です
            std::cout << "判定: 中堅 — 一人前として認められています" << std::endl;
            break;

        case 2:
            // 組の中核を担う幹部クラスです
            std::cout << "判定: 幹部 — 組の中枢を担います" << std::endl;
            break;

        case 3:
            // 最高幹部と組長クラスは同じ扱いをします
            // [[fallthrough]] で case 3 と case 4 を共通処理にします
            [[fallthrough]];

        case 4:
            std::cout << "判定: 頂点 — 伝説クラスの強さです" << std::endl;
            break;

        default:
            // 定義外のランクが渡された場合の安全策です
            std::cout << "判定: 不明 — ランク値が不正です" << std::endl;
            break;
    }

    // ----------------------------------------
    // 初期化付き switch(C++17)のサンプルです
    // ----------------------------------------
    // 変数 evaluator のスコープを switch 内に限定します
    switch (std::string evaluator = "桐生一馬"; rank) {
        case 0:
            std::cout << evaluator << ": まだ修行が必要だな" << std::endl;
            break;
        case 2:
            std::cout << evaluator << ": 筋はいい、もっと鍛えろ" << std::endl;
            break;
        default:
            std::cout << evaluator << ": 見ておこう" << std::endl;
            break;
    }

    return 0;
}
# C++17 規格を指定してコンパイルします(初期化付き switch に必要です)
g++ -std=c++17 battle_rank.cpp -o battle_rank

# 実行します
./battle_rank
【極道バトルランク判定】
ファイター: 真島吾朗
判定: 幹部 — 組の中枢を担います
桐生一馬: 筋はいい、もっと鍛えろ

よくあるミス

break の書き忘れによって意図しない fallthrough が発生するのは、switch 文でもっとも多いバグのひとつです。次の例では case 1 の末尾に break がないため、case 2 の処理まで続けて実行されます。

fallthrough_bug.cpp
// NG: break 忘れによる意図しない fallthrough
#include <iostream>

int main() {
    int rank = 1;

    switch (rank) {
        case 1:
            std::cout << "錦山彰: 中堅幹部です" << std::endl;
            // break を書き忘れています — case 2 に流れ落ちます
        case 2:
            std::cout << "嶋野雅: 最高幹部です" << std::endl;
            break;
        default:
            std::cout << "不明なランクです" << std::endl;
            break;
    }

    return 0;
}
g++ -std=c++17 fallthrough_bug.cpp -o fallthrough_bug
./fallthrough_bug
錦山彰: 中堅幹部です
嶋野雅: 最高幹部です

rank が 1 であるにもかかわらず、case 2 の出力まで実行されています。各 case の末尾には必ず break; を書いてください。

// OK: 各 case に break を明示します
#include <iostream>

int main() {
    int rank = 1;

    switch (rank) {
        case 1:
            std::cout << "錦山彰: 中堅幹部です" << std::endl;
            break;  // ここで switch を抜けます
        case 2:
            std::cout << "嶋野雅: 最高幹部です" << std::endl;
            break;
        default:
            std::cout << "不明なランクです" << std::endl;
            break;
    }

    return 0;
}
g++ -std=c++17 fallthrough_ok.cpp -o fallthrough_ok
./fallthrough_ok
錦山彰: 中堅幹部です

意図的に fallthrough させたい場合は C++17 の [[fallthrough]]; 属性を使います。この属性を付けることで「わざと次の case に流すつもりである」とコンパイラに伝え、警告を抑制できます。

// OK: 意図的な fallthrough は [[fallthrough]] で明示します
#include <iostream>

int main() {
    int rank = 3;

    switch (rank) {
        case 3:
            // 最高幹部と組長は同じ「頂点」扱いにします
            [[fallthrough]];  // 意図的に case 4 へ流します
        case 4:
            std::cout << "桐生一馬 / 真島吾朗: 伝説クラスです" << std::endl;
            break;
        default:
            std::cout << "一般幹部です" << std::endl;
            break;
    }

    return 0;
}
g++ -std=c++17 fallthrough_attr.cpp -o fallthrough_attr
./fallthrough_attr
桐生一馬 / 真島吾朗: 伝説クラスです

概要

switch 文の条件式に使えるのは整数型・char 型・列挙型(enum)に限られます。std::string などの文字列型は使用できないため、文字列による分岐が必要な場合は if-else if や連想コンテナ(std::map 等)を使用してください。break の書き忘れによる意図しない fallthrough はバグの温床になりやすいため、C++17 以降では意図的な fallthrough に [[fallthrough]]; 属性を付けることでコンパイラの警告を抑制しつつ意図を明示できます。初期化付き switch(C++17)は条件判定に使う変数のスコープをブロック内に収められるため、名前空間の汚染を防ぐ上で有効です。コンパイル時は -std=c++17 オプションを指定してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。