JPCERT コーディネーションセンター

INT09-C. 列挙定数が一意の値に対応することを保証する

INT09-C. 列挙定数が一意の値に対応することを保証する

C言語の列挙型は、列挙定数として知られる識別子、つまり列挙子によって表される有限個の値からなる型を定義する。列挙子は、値を int として表現可能な整数定数式である。言語仕様では、同じ型の複数の列挙子が同じ値を持ってもよいとされているが、一般には、同じ型に属する各列挙子は互いに異なる値を持つことが期待されるだろう。同じ型に属する複数の列挙子が同じ値を持つように定義すると、自明でないエラーにつながる可能性がある。

違反コード

以下のコード例では、Color 型の 2 つの列挙子の値が明示的に定義されている。プログラマには自明ではないかもしれないが、yellowindigo の値は 6 となり、greenviolet の値は 7 となる。このような定義から生じる最も危険性の低いエラーは、これらの列挙子を switch 文のラベルとして使うことだろう。switch 文のラベルは互いに異なる値であることが要求されるため、次のようなコードを規格合致処理系でコンパイルすると診断メッセージが出力されることになる。

enum Color { red=4, orange, yellow, green, blue, indigo=6, violet };

const char* color_name(enum Color col) {
  switch (col) {
  case red: return "red";
  case orange: return "orange";
  case yellow: return "yellow";
  case green: return "green";
  case blue: return "blue";
  case indigo: return "indigo";   /* Error: duplicate label (yellow) */
  case violet: return "violet";   /* Error: duplicate label (green) */
  }
}
適合コード

違反コード例で説明したエラーを防ぐためには、列挙型宣言を次の形式のいずれかにする必要がある。

enum Color { red, orange, yellow, green, blue, indigo, violet };
enum Color { red=4, orange, yellow, green, blue, indigo, violet };
enum Color {
  red=4, 
  orange=5, 
  yellow=6, 
  green=7, 
  blue=8, 
  indigo=6, 
  violet=7
};

また、将来コードをメンテナンスする人がこれを間違いだと誤解しないように、なぜ複数の列挙型メンバに同じ値を代入しているのかを説明するコメントをつけておくのがオススメだ。

最初の列挙子がゼロ以外の値である必要がなければ、3つのオプションのうち最初の「明示的な整数の代入をしない」が最もシンプルで好ましい方法である。

例外

INT09-EX1: 同じ値の列挙子を2つ以上持つ列挙型を定義したい場合は、重複する値を持たせたい列挙子の値を、元の列挙子を使って定義すべきである。これにより、同じ値にしたいという意図を、コードを読む人にもコード分析ツールにも明確に伝えることができる。ただし、このように定義された列挙子は、一意の値が必要なコンテキスト (前述の switch 文など) では使えない点に注意。

enum Color { red, orange, yellow, green, blue, indigo, violet=indigo };
リスク評価

列挙型の各メンバが一意の値を持つことを保証しておかないと、予期せぬ結果を招くおそれがある。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

INT09-C

P4

L3

自動検出

ツール

バージョン

チェッカー

説明

CodeSonar 4.0 LANG.STRUCT.ENUMINIT Inconsistent Enumerator Initialization

Compass/ROSE

 

 

 

ECLAIR

1.2

CC2.INT09

実装済み

LDRA tool suite

8.5.4

85 S

実装済み

PRQA QA-C v8.2

0724

実装済み
関連するガイドライン
CERT C++ Coding Standard INT09-CPP. Ensure enumeration constants map to unique values
CERT Oracle Secure Coding Standard for Java 28. Do not attach significance to the ordinal associated with an enum
ISO/IEC TR 24772:2013 Enumerator Issues [CCB]
MISRA C:2012 Rule 8.12 (required)
翻訳元

これは以下のページを翻訳したものです。

INT09-C. Ensure enumeration constants map to unique values (revision 70)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter