switch…case の解説と実装リファレンス

記事内には広告が含まれています。

switch…case の解説と実装リファレンス

【概要】

switch...case 文は、評価された式の結果に基づいて、複数の分岐パスのいずれかを実行するための制御構造です。Arduino(C/C++)において、特定の変数や式の値に応じて異なる処理を動的に選択する場合に用いられます。論理的には「多方向分岐」を簡潔に記述するための構文であり、複雑な if...else if...else のネストを回避し、コードの可読性を向上させる役割を果たします。

【仕様】

  • 評価対象(式): 基本的に整数型(int, char, short, long, byte, enum 等)の評価結果を対象とします。浮動小数点数(float, double)や文字列(String, char*)は直接の比較対象にはできません。
  • case ラベル: 定数式である必要があります。変数を case に直接指定することはできません。
  • break 文: 各 case ブロックの末尾に break; を記述することで、次の case への「フォールスルー(fall-through)」を停止させます。
  • default 文: いずれの case 条件にも一致しない場合に実行されるパスです。予期しない入力に対する安全策として記述することが推奨されます。

【技術的特徴】

1. ジャンプテーブルによる最適化

コンパイラは、switch 文の case ラベルが連続した整数値である場合、内部的に「ジャンプテーブル(Jump Table)」を生成することがあります。これにより、if...else if を連続して評価する(O(n))のに対し、特定のインデックスへ直接ジャンプする(O(1))という計算量的優位性が得られる場合があります。

2. if…else との比較

  • if…else: 複雑な論理演算(&&, ||)や範囲指定(x > 10)が必要な場合に適しています。
  • switch…case: 単一の変数に対する離散的な値の比較に適しており、構造化されたコードの保守性が高まります。

3. Enum との親和性

Arduino開発において、状態を定義する enum 型と組み合わせることで、状態遷移の可読性を最大化できます。

【注意点】

  • フォールスルーの制御: break を忘れると、次の case の処理まで連続して実行されます。意図的なフォールスルーが必要な場合は、明示的に設計を意識する必要があります(C++17以降では [[fallthrough]]; 属性が利用可能)。
  • 変数スコープ: case ブロック内で変数を宣言・初期化する場合、その変数は switch 全体のスコープを持ちます。特定の case 内だけで変数を限定したい場合は、ブロック { ... } で囲んでスコープを制限する必要があります。
  • 浮動小数点数の制約: 浮動小数点数を判定したい場合は、switch を直接使うことはできず、範囲判定を行う if 文を用いるか、整数にキャストして評価する設計変更が必要です。
  • メモリ制約: 大規模なジャンプテーブルが生成される場合、極端に稀なケースにおいてメモリ消費に影響を与える可能性があります(通常の Arduino 環境では稀です)。

【サンプルコード】

以下は、ボタン入力によってLEDの状態を遷移させる状態遷移マシン(FSM)の例です。

enum State {
  OFF = 0,
  ON = 1,
  BLINK = 2
};

State currentState = OFF;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // 外部入力のシミュレーション(例:シリアル入力で状態を変化させる)
  if (Serial.available() > 0) {
    char input = Serial.read();
    if (input == '1') currentState = ON;
    if (input == '2') currentState = BLINK;
    if (input == '0') currentState = OFF;
  }

  // switch文による状態制御
  switch (currentState) {
    case ON:
      digitalWrite(LED_BUILTIN, HIGH);
      break;

    case OFF:
      digitalWrite(LED_BUILTIN, LOW);
      break;

    case BLINK:
      digitalWrite(LED_BUILTIN, (millis() / 500) % 2 == 0 ? HIGH : LOW);
      break;

    default:
      // 予期しない状態への安全策
      digitalWrite(LED_BUILTIN, LOW);
      break;
  }
}

【活用例】

  1. 状態遷移マシン (FSM): 機器の動作状態(待機、起動中、動作中、エラー、停止)の管理。
  2. 通信プロトコルの解析:
    UARTやI2Cで受信したコマンドバイトを判定し、それに応じた処理(Read, Write, Config等)を振り分ける処理。
  3. メニューシステムの構築:
    ボタン入力によって選択されたメニュー番号に応じて、表示内容や動作を切り替える処理。
  4. キーパッド入力処理:
    押されたキーのID(0〜9など)に応じて、特定の操作を実行する分岐処理。

コメント

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