GAIO CLUB

2023年01月23日

【第3回】理解しづらいコーディングガイドラインとは? ~switch文~

静的解析/コンパイラ技術
いまさら聞けない 静的解析/コンパイラ技術
引き続き、難解なガイドラインについてお話しします。

今回はswitch文に関するものです。

caseラベルとdefaultラベル

このようなルールがあります。

"switchラベルは、それを直接内包している複合文が、switch文の本体である場合にだけ用いる"

少し解りにくいですね。つまり、こういうことです。
#include<stdio.h>

  void test(int i)
  {
    switch(i)
    {
      case 10 : {
                  printf(" case 10\n");
                  case 11 : printf(" case 11\n");  /* ルール違反 */
                  break;
                }
                break;
      case 20 : {
                  printf(" case 20\n");
                  case 21 : printf(" case 21\n");  /* ルール違反 */
                  break;
                }
                break;
      case 30 : {
                  printf(" case 30\n");
                  case 31 : printf(" case 31\n");  /* ルール違反 */
                  break;
                }
                break;
      default : {
                  printf(" default\n");
                }
                break;
      }
    return;
  }
  
  int main(void)
  {
    test(10);
    test(11);
    test(12);
    test(20);
    test(21);
    test(22);
    test(30);
    test(31);
    test(32);
    return 0;
  }
switch文直下のブロック以外に caseやdefaultラベルを書くのは禁止です。
そもそも、他のブロック内にswitchラベルが書けると思っていない人が多いかもしれませんが、知ってる人は例のようなコードを書くかもしれません。

このプログラムは文法上正しいので、エラーなしにコンパイルでき、動作結果は以下の通りです。
  case 10
  case 11
  case 11
  default
  case 20
  case 21
  case 21
  default
  case 30
  case 31
  case 31
  default

その他のルール

switch文に関するガイドラインには、他にもこんなルールがあります。
・ 空でないswitch節はbreak文で終わる
・すべてのswitch文はdefault節を持つ
・switch文の最後の節はdefault節とする
・switch文の式に真偽評価式等のブール値を用いない
・ 最低1つのcase節を持つ
空のswitch節でない限りbreakが必要なので、たとえば以下の例はルール違反になります。
#include<stdio.h>
  int X,Y,Z;
  void test(int i)
  {
    switch(i)
    {
      case 1  : X++;
      case 2  : Y++;
      case 3  : Z++;
      default : printf(" X(%d) Y(%d) Z(%d)\n",X,Y,Z);
                  break;
    }
    return;
  }
  
  int main(void)
  {
    X = Y = Z = 0;
    test(1);
    test(2);
    test(3);
    return 0;
  }
このプログラムの動作結果はこうなります。
  X(1) Y(1) Z(1)
  X(1) Y(2) Z(2)
  X(1) Y(2) Z(3)
gotoは使用するなという別のルールもありますが、gotoとラベルはプログラムを複雑にします。

このルールは、switch文についても分岐の状態を複雑にさせないために、ひとつのswitch節で処理を終了させ、飛び先のないswitch文を作らせないのが狙いでしょう。


筆者紹介

浅野 昌尚(あさの まさなお)

ガイオ・テクノロジー株式会社

開発1部 QTXグループ

1980年代から30年以上にわたり汎用構造のCコンパイラ開発に従事し、その間に8ビットマイコンからRISC・VLIW・画像処理プロセッサまで、さまざまなCPU向けのクロスCコンパイラを開発。

人気のコラム

最新のコラム