switch 文 は、switch 式の値に応じて、switch 本体内の別のステートメントに制御を移す選択ステートメントです。 switch 式の評価は、整数値または列挙値にならなければなりません。switch 文の本体には、以下で構成される case 文節 が含まれています。
switch 式の値が case 式の 1 つの値と同じ場合、 その case 式に続くステートメントが処理されます。 そうでない場合、default ラベル・ステートメント (あれば) が処理されます。
switch 文の形式は、次のとおりです。
>>-switch--(--expression--)--switch_body-----------------------><
switch 本体 は、中括弧で囲まれ、定義、宣言、case 文節、 および default 文節 を含むことができます。 case 文節と default 文節のそれぞれにステートメントを含めることができます。
.----------------------------------. V | >>-{----+------------------------------+-+----------------------> +-type_definition--------------+ +-file_scope_data_declaration--+ '-block_scope_data_declaration-' .-----------------. V | >----+-------------+-+--+----------------+----------------------> '-case_clause-' '-default_clause-' .-----------------. V | >----+-------------+-+--}-------------------------------------->< '-case_clause-'
case 文節 には、任意の数のステートメントが続く case label が含まれます。 case 文節の形式は、次のとおりです。
.-----------. V | >>-case_label----statement-+-----------------------------------><
case ラベル には、case というワードと、それに続く整数定数式とコロンが入っています。各整数定数式の値は、別々の値を表している必要があります。 重複した case ラベルを持つことはできません。1 つの case ラベルを置けるところであればどこでも、複数の case ラベルを置くことができます。case ラベルの形式は、次のとおりです。
.---------------------------------------. V | >>---case--integral_constant_expression--:-+-------------------><
default 文節 には、default ラベルと、 それに続く 1 つまたは複数のステートメントが入っています。 case ラベルは、default ラベルのどちらの側にも置くことができます。 switch 文に入れることができる default ラベルは、1 つだけです。 default_clause の形式は、次のとおりです。
.-----------. V | >>-+------------+--default--:--+------------+----statement-+--->< '-case_label-' '-case_label-'
switch 文は、いずれか 1 つのラベルに続くステートメント、 または switch 本体に続くステートメントに制御を 渡します。switch 本体の前にある式の値によって、制御を受け取る ステートメントが決まります。この式は switch 式 と呼ばれます。
switch 式の値は、各 case ラベルの式の値と比較されます。 一致している値が検出されれば、一致したその値が入っている case ラベルに続くステートメントに、 制御が渡されます。 一致する値はないが、switch 本体の中に default ラベルがある場合には、default ラベルの付いたステートメントに制御が渡されます。 一致する値が見つからず、switch 本体の中のどこにも default ラベルがない場合には、switch 本体のどの部分も処理されません。
switch 本体の中のステートメントに制御が渡されると、 break ステートメントが検出されたとき、 または switch 本体の中の最後のステートメントが処理されたときにのみ、 制御は switch 本体を離れます。
必要であれば、整数拡張が、制御式上で実行されます。 また、case ステートメント内のすべての式が、制御式と同じ型に変換されます。 switch 式は、整数型または列挙型への単一変換があれば、クラス型の式にもなります。
オプション -qinfo=gen でコンパイルすると、必要ない場合に中止する case ラベルが検出されます。
制約および制限事項
データ定義を switch 本体の先頭に置くことができますが、 コンパイラーは、switch 本体の先頭にある auto および register 変数は、 初期化しません。 switch 文の本体の中に、宣言を入れることができます。
switch 文を使用して、初期化を飛び越えることはできません。
可変的に変更される型を持つ ID の
スコープに、switch 文の case またはデフォルトのラベルが含まれている場合は、switch
文全体がその ID のスコープ内にあるものと見なされます。
つまり、その ID の宣言は
switch 文よりも前にある必要があります。
C++ では、暗黙的または明示的な初期化指定子を含んでいる宣言を超えて、
制御権を移動することはできません。
ただし、宣言が、制御権の移動によって完全に迂回される内部ブロックに入っている場合は、
制御権を移動することができます。
初期化指定子が入っている switch 文本体内の宣言はすべて、
内部ブロックに入れる必要があります。
switch 文の例
以下の switch 文には、複数の case 文節 と 1 つの default 文節が入っています。各文節には、関数呼び出しと break ステートメント が入っています。break ステートメントは、switch 本体内の 各ステートメントに制御が移されていくのを防止します。
switch 式の評価が '/' となった場合、その switch 文は 関数 divide を呼び出すことになります。その後、switch 本体に続くステートメントに 制御が渡されます。
char key; printf("Enter an arithmetic operator¥n"); scanf("%c",&key); switch (key) { case '+': add(); break; case '-': subtract(); break; case '*': multiply(); break; case '/': divide(); break; default: printf("invalid key¥n"); break; }
switch 式と case 式が一致した場合には、break ステートメントが検出されるまで、 または switch 本体の終わりに達するまで、case 式に続くステートメントが処理されます。 以下の例には、break ステートメントはありません。 text[i] の値が 'A' である場合、 コンパイラーは、3 つのカウンターすべてを増やします。 text[i] の値が 'a' と等しい場合 には、lettera と total が増やされます。 text[i] が 'A' または 'a' と等しくない場合には、total のみが増やされます。
char text[100]; int capa, lettera, total; // ... for (i=0; i<sizeof(text); i++) { switch (text[i]) { case 'A': capa++; case 'a': lettera++; default: total++; } }
次の switch 文は、複数の case ラベルに対して同じステートメントを 実行します。
/** ** This example contains a switch statement that performs ** the same statement for more than one case label. **/ #include <stdio.h> int main(void) { int month; /* Read in a month value */ printf("Enter month: "); scanf("%d", &month); /* Tell what season it falls into */ switch (month) { case 12: case 1: case 2: printf("month %d is a winter month¥n", month); break; case 3: case 4: case 5: printf("month %d is a spring month¥n", month); break; case 6: case 7: case 8: printf("month %d is a summer month¥n", month); break; case 9: case 10: case 11: printf("month %d is a fall month¥n", month); break; case 66: case 99: default: printf("month %d is not a valid month¥n", month); } return(0); }
式 month の値が 3 の場合には、 次のステートメントに制御が渡されます。
printf("month %d is a spring month¥n", month);
break ステートメントは、switch 本体に続く ステートメントに制御を渡します。
関連参照