switch文 - 整数の高速な条件分岐
switch文を使うと、整数の高速な条件分岐を行うことができます。
switch (値) { case ケース1の値: // 処理1 break; case ケース2の値: // 処理2 break; case ケース3の値: // 処理3 break; default: // 上記以外のケースの場合の処理 }
break文は必須ではありませんが、breakがない場合は、switch文の外には移動せずに、下の文が実行されます。
switch (値) { case ケース1の値: case ケース2の値: // ケース1あるいはケース2の場合の処理 break; case ケース3の値: // 処理3 break; default: // 上記以外のケースの場合の処理 }
break文の記述のし忘れは、経験的に語ると、頻繁に発生します。「あれ、おかしいな、プログラムの動きが謎過ぎる」と思ったらbreak文書き忘れてたみたいな。
switch文のそれぞれの場合の処理では、変数宣言を行いたい場合も多いので、変数宣言を行いたい場合は、以下のようにスコープを作っておくとよいでしょう。
switch (値) { case ケース1の値: { // 処理1 break; } case ケース2の値: { // 処理2 break; } case ケース3の値: { // 処理3 break; } default: { // 上記以外のケースの場合の処理 } }
switch文を使ったサンプルです。列挙型と組み合わせて使っています。
#include <stdint.h> #include <stdio.h> enum { SPVM_OP_C_ID_IF, SPVM_OP_C_ID_UNLESS, SPVM_OP_C_ID_ELSIF, SPVM_OP_C_ID_ELSE, SPVM_OP_C_ID_FOR, }; int main(void) { int32_t id = SPVM_OP_C_ID_UNLESS; switch (id) { case SPVM_OP_C_ID_IF: { printf("IF\n"); break; } case SPVM_OP_C_ID_UNLESS: { printf("UNLESS\n"); break; } case SPVM_OP_C_ID_ELSIF: { printf("ELSIF\n"); break; } case SPVM_OP_C_ID_ELSE: { printf("ELSE\n"); break; } case SPVM_OP_C_ID_FOR: { printf("FOR\n"); break; } default: { printf("No Match\n"); } } }
switch文の内部実装はどうなっていますか?
整数のパターンによって、二種類のジャンプテーブルが選択的に使われていると想像します。
整数の範囲が小さい場合
ジャンプ先のアドレスは、連続した整数位置に並べられ、計算量O(1)でジャンプできます。
5 0x1235 6 0x4568 7 NULL 8 NULL 9 0x3289
整数の範囲が大きい場合
ジャンプ先のアドレスは、二分探索が可能なように小さい順に並べられ、計算量O(log n)でジャンプできます。
5 0x1237 6 0x4563 7000 0x8768 10000 0x3284
if文とswitch文はどのように使い分けますか?
if文とswitch文はどのように使い分けるでしょうか?
switch文は、整数にマッチする場合にだけ使います。switch文は、列挙型との相性が非常によいです。
また、マッチさせる数が多い場合は、if文よりも速いです。たとえば、255個のIDで分岐したい場合は、switch文は高速で適しているといえます。