switch文
switch文(スイッチぶん)とは、プログラミング言語において、ある式の値に応じて多分岐をおこなう文である。
最適化の仕方によって多少変わることはあるが、場合によってはテーブルジャンプなどにより、条件判断を繰り返すif文より効率的に実行される。
目次 |
文法 [編集]
C [編集]
構文は以下の通り。
switch (制御式) { case 値1: 文 文 ……… break; case 値2: 文 文 ……… break; default: 文 }
上記の「case」はいくつでも記述することができる。
この文は次のような手順で実行される。
- 制御式を評価し、整数値を得る。
- その整数値がどれかのcaseで指定された値であるなら、そのcaseに引き続く文に飛ぶ。
- どのcaseでも指定されていなければ、defaultに引き続く文に飛ぶ。
- もしdefaultが記述されていなければ、何も実行せずにswitch文を抜ける。
フォールスルー [編集]
ここで注意しなければならないのが、caseはラベルに過ぎず、そのcaseより前からの実行から、そこでswitch文を抜けさせる働きはない点である(一般的には、次のcaseがあらわれる直前にbreak文を置く)。このルールはフォールスルー(fall through)と言い、制御の流れが合流する動作をさせたい場合に便利であるが、一方でbreak文の書き忘れによるバグ、ループを抜けるbreakと取り違える誤読によるバグなど、バグの温床として問題視されてきた。
そのためlintでは、意図的にフォールスルーしていることを示す/* FALLTHROUGH */などのコメントが記述されていない限り警告を出す。また、Cに類似した構文を採用した言語でも、C#のように対策(後述)した言語仕様にされていることがある。
上記の例は、if文を羅列することで同様の動作を実現することができる。
_tmp_ = 制御式; if (_tmp_ == 値) { 文 } else if (_tmp_ == 値) { 文 } ……… else { 文 }
defaultは最後に記述される場合が多いが、必ずしも最後である必要はない。
switchによる分岐は以下のようにdo-while文と組み合わせることも可能である。
switch(count) { default: do { printf("%d\n", count); count++; case 0: printf("%d\n", count); count++; case 1: printf("%d\n", count); count++; case 2: printf("%d\n", count); count++; } while (count); }
例えばDuff's deviceではそのような使われ方をしている。
C# [編集]
C#では「goto case」が使える
switch (someInteger) { case 0: case 1: return 1; // 変数someIntegerが0か1の時に実行 case 2: someInteger++; goto case 3: // case 3も実行 case 3: 文A; break; default: 文B; break; }
C#では、文が1個も存在しない場合に限り、フォールスルーするcaseを書ける。文が存在するcaseでは、必ずbreakするか、goto caseしなければならない。goto caseにより、C言語ではフォールスルーを使って書くことができた、制御の合流を書くことができる。
C#では、CやC++が整数型しか制御式の値に使用できないのに対し、文字列型も使用できる。
Go [編集]
Goでは、caseに複数の値を指定できる。次のcaseの直前にfallthrough文を置くとフォールスルーになる。
PHP [編集]
PHPでは、C#と同様、文字列にも、switch文が適用できる。
switch (str) { case "ABC": 文A; break; case "XYZ": 文B; break; case "123": 文C; break; default: 文D; break; }
BASIC [編集]
構造化されたBASICでは、Select Caseステートメントが存在することが多い。このステートメントでは、文字列または整数を対象にできる。
Select Case str Case "ABC" 文A Case "XYZ" 文B Case "123" 文C Case Else 文D End Select
Select Case age Case Is < 20 文A Case 20 To 29 文B Case 30,50,70 文C Case Else 文D End Select
Cなどと違い、各Caseはラベルではなく、Selectステートメントはフォールスルーでない。
Perl [編集]
Perlでは、perl-5.8以降からuse Switchとした上でswitch case文が使えるようになった。それ以前のバージョンのperlに関しては、Perl付属文章perlsynドキュメントのBasic BLOCKs and Switch Statementsの節に書式の例が書かれている。
Ruby [編集]
Rubyでは、case式により同様の多分岐ができる。フォールスルーはない。ラベルとして範囲オブジェクトを指定できる。