switch 文の書き方

 まがりなりにも構造化言語と呼ばれるC 言語の中では,switch 文は,かなり特異な制御構造をしている.その switch 文の書き方について解説する.

次は, switch 文の標準的な使い方である.

    switch (x) {
        case 1 :
            printf("one");
            break;
        case 2 :
            printf("two");
            break;
        default :
            printf("other");
            break;
    }

この switch 文を実行すると,変数 x (必ず int 型でなければならない)の値が 1 のときは one,2のときは two,それ以外のときは other を表示する.
ここで注意すべき点は,それぞれの場合に実行される部分の最後に break がついていることである(最後の default についた break は必要ではない).
なぜ,break が必要なのか.その理由は, switch 文が本質的には goto 文であることにある.

    switch (x) {
        case 1 :
            printf("one");
        case 2 :
            printf("two");
        default :
            printf("other");
    }

上の switch 文は,goto 文で書かれた次のものに同じである.

    if (x == 1) goto case1;
    if (x == 2) goto case2;
    goto defaultcase;

    case1 :
        printf("one");
    case2 :
        printf("two");
    defaultcase :
        printf("other");

これを実行すると, x の値が1のときは onetwoother ,2のときは twoohter,それ以外のときは other を表示する.したがって,x==1 のときには "one"の表示で止めたいときには, 次のように break をつける必要がある.この break により,switch 文本体,すなわち switch の直後の { } から抜け出ることになる.

        case 1 :
            printf("one");
            break;
    switch (x) {
        case 1 :
            printf("one");
            break;
        case 2 :
            printf("two");
            break;
        default :
            printf("other");
            break;
    }

上の switch 文を, goto 文で表すと次のようになる。

    if (x == 1) goto case1;
    if (x == 2) goto case2;
    goto defaultcase;

    case1 :
        printf("one");
        goto end;
    case2 :
        printf("two");
        goto end;
    defaultcase :
        printf("other");
        goto end;

    end :;

ところで,switch 文は本質的に goto 文であるから,switch 文の本体内であれば,case ラベルはほとんど至る所に付けることができる.次の switch 文はまったく問題なく働く.

    switch (a) {
        case 1 :
            printf("a==1");
            if (b == 3) {
        case 2 :
                printf("a==1 and b==3 or a==2");
            }
            break;
        default :
            printf("other");
            break;
    }

しかし,このようなコーディングはあまり勧められない.

また,case ラベルをほとんど至る所に付けることができるとは言っても,入れ子になった内側の switch 文本体内には無理である.付けてもいいが,それは内側の switch 文のラベルとなる.

    switch (a) {
        case 1 :
            printf("a==1");
            break;
        case 2 :
            printf("a==2");
            switch (b) {
                case 1: 
                    printf("b == 1");
        case 3 :                          /* これは無理 */
                    printf("a == 3");
            }
        default :
            printf("other");
            break;
    }