Namespaces
Variants

Enumerations

From cppreference.net

enumerated type は、その underlying type (下記参照)の値である値を持つ個別の type であり、明示的に名前が付けられた定数( enumeration constants )の値を含みます。

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - HTMLタグ、属性、
タグ内のテキストは翻訳していません
- C++関連の専門用語(Syntax、Explanation、Notes、Example、References、Keywords、See also)は原文のまま保持しています
- 数値や構造は完全に保持されています
- フォーマットとレイアウトは元のまま維持されています

構文

列挙型は以下の 列挙指定子 宣言文法 における type-specifier として使用して宣言されます:

enum attr-spec-seq  (オプション) identifier  (オプション) { enumerator-list } (1)
enum attr-spec-seq  (オプション) identifier  (オプション) : type { enumerator-list } (2) (C23以降)
1) 固定された基底型を持たない列挙型を宣言します。
2) 固定された基盤型 type を持つ列挙型を宣言します。

where enumerator-list はカンマ区切りのリスト (末尾のカンマが許可される) (C99以降) であり、各要素は以下の形式を持ちます:

enumeration-constant attr-spec-seq  (optional) (1)
enumeration-constant attr-spec-seq  (optional) = constant-expression (2)

ここで

identifier , enumeration-constant - この宣言によって導入される識別子
constant-expression - 整数定数式 その値が型 int の値として表現可能な (C23まで) 列挙型が固定された基底部型を持つ場合、 type の値として表現可能な (C23以降)
attr-spec-seq - (C23) オプションの 属性 リスト、
  • enum の後に現れる場合は列挙全体に適用される
  • enumeration-constant の後に現れる場合は enumerator に適用される

struct union と同様に、列挙型と1つ以上の列挙定数を導入する宣言は、その型またはその型から派生した型の1つ以上のオブジェクトも宣言することができます。

enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// enum color型を導入
// 整数定数RED, GREEN, BLUE
// enum color型のオブジェクトc
// enum colorへのポインタ型のオブジェクトcp

説明

列挙指定子の本体に現れる各 enumeration-constant は、囲んでいるスコープで 整数定数 となり、その型は int (C23まで) です。これは整数定数が必要な場面(例えばcaseラベルや非VLA配列のサイズなど)で使用できます。

列挙子リスト内の各列挙定数の処理中に、列挙定数の型は以下のいずれかでなければならない:

  • 同じ列挙定数の再宣言である場合、以前に宣言された型;または、
  • 固定された基底型を持つ列挙型の場合、列挙型;または、
  • int 、列挙子リスト内に以前の列挙定数がなく、定義整数定数式を持つ明示的な=がない場合;または、
  • int 、=で明示的に指定され、整数定数式の値がintで表現可能な場合;または、
  • =で明示的に指定され、整数定数式の値が int で表現できない場合、整数定数式の型;または、
  • 最後の列挙定数の値に1を加えた値の型。そのような整数定数式が前の列挙定数の値に1を加えることでオーバーフローまたはラップアラウンドする場合、型は以下のいずれかを取る:
    • 前の列挙定数の値に1を加えた値を表現できる適切なサイズの符号付き整数型(ビット精度符号付き整数型を除く);または、
    • 前の列挙定数の値に1を加えた値を表現できる適切なサイズの符号なし整数型(ビット精度符号なし整数型を除く)。

加算される前の列挙定数が符号付き整数型の場合、符号付き整数型が選択される。前の列挙定数が符号なし整数型の場合、符号なし整数型が選択される。新しい値を表現できる前述の適切なサイズの整数型が存在しない場合、その列挙型はすべての値を表現できる型を持たない。

(C23以降)
enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
    puts("red");
    break;
case GREEN:
    puts("green");
    break;
case BLUE:
    puts("blue");
    break;
}

enumeration-constant の直後に = constant-expression が続く場合、その値はその定数式の値となります。 enumeration-constant の直後に = constant-expression が続かない場合、その値は同じ列挙型内の前の列挙子の値より1大きい値となります。最初の列挙子の値( = constant-expression を使用しない場合)はゼロです。

enum Foo { A, B, C = 10, D, E = 1, F, G = F + C };
// A=0, B=1, C=10, D=11, E=1, F=2, G=12

identifier 自体が使用される場合、それはタグ name space 内の列挙型の名前となり、enumキーワードの使用を必要とします(typedefによって通常のname spaceに移されない限り)。

enum color { RED, GREEN, BLUE };
enum color r = RED; // OK
// color x = GREEN; // エラー: colorは通常の名前空間に存在しない
typedef enum color color_t;
color_t x = GREEN; // OK

固定された基底型を持たない列挙型 固定された基底型を持たない (C23以降) は、以下のいずれかと 互換 である: char 、符号付き整数型、または符号なし整数型 ( bool およびビット精度整数型を除く) (C23以降) 。どの型が特定の列挙型と互換であるかは実装定義であるが、どの型であってもその列挙のすべての列挙子の値を表現できなければならない。 固定された基底型を持つすべての列挙型について、列挙型はその列挙の基底型と互換である。 (C23以降)

固定された基底型を持たない列挙型の列挙メンバーの型は、列挙の完了時に以下のいずれかとなります:

  • int 列挙のすべての値が int として表現可能な場合;または、
  • 列挙型自体。
(C23以降)
すべての列挙型は基底型を持ちます。基底型はenum-type-specifierを使用して明示的に指定でき、それが固定された基底型となります。明示的に指定されない場合、基底型は列挙の互換型であり、符号付きまたは符号なし整数型、または char のいずれかです。 (C23以降)

列挙型は整数型であり、したがって他の整数型が使用できる場所であればどこでも使用できます。これには 暗黙的変換 および 算術演算子 も含まれます。

enum { ONE = 1, TWO } e;
long n = ONE; // プロモーション
double d = ONE; // 変換
e = 1.2; // 変換、eは現在ONE
e = e + 1; // eは現在TWO

注記

C言語では、 struct union とは異なり、前方宣言されたenumは存在しません:

enum Color; // エラー: C言語ではenumの前方宣言はできません
enum Color { RED, GREEN, BLUE };

列挙型は、 #define よりも便利で構造化された方法で名前付き定数を宣言することを可能にします。これらはデバッガで可視化され、スコープ規則に従い、型システムに参加します。

#define TEN 10
struct S { int x : TEN; }; // OK

または

enum { TEN = 10 };
struct S { int x : TEN; }; // こちらも有効

C23以降、 constexpr が同じ目的で使用できます:

constexpr int TEN = 10;
struct S { int x : TEN; }; // こちらも有効

さらに、C言語では struct または union はスコープを確立しないため、列挙型とその列挙定数は前者のメンバー指定内で導入することができ、それらのスコープは前者と同じになります。

struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// 列挙型Stateとその列挙定数はここでも可視です。例:
void foo(void)
{
    enum State e = LIQUID; // OK
    printf("%d %d %d ", e, oxygen.state, PLASMA); // 1 2 3 を出力
}

#include <stdio.h>
int main(void)
{
    enum TV { FOX = 11, CNN = 25, ESPN = 15, HBO = 22, MAX = 30, NBC = 32 };
    printf("List of cable stations:\n");
    printf(" FOX: \t%2d\n", FOX);
    printf(" HBO: \t%2d\n", HBO);
    printf(" MAX: \t%2d\n", MAX);
}

出力:

List of cable stations:
 FOX:   11
 HBO:   22
 MAX:   30

参考文献

  • C23規格 (ISO/IEC 9899:2024):
  • 6.2.5/21 型 (p: 39)
  • 6.7.2.2 列挙子指定子 (p: 107-112)
  • C17規格 (ISO/IEC 9899:2018):
  • 6.2.5/16 型 (p: 32)
  • 6.7.2.2 列挙型指定子 (p: 84-85)
  • C11 standard (ISO/IEC 9899:2011):
  • 6.2.5/16 型 (p: 41)
  • 6.7.2.2 列挙子指定子 (p: 117-118)
  • C99規格 (ISO/IEC 9899:1999):
  • 6.2.5/16 型 (p: 35)
  • 6.7.2.2 列挙子指定子 (p: 105-106)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.1.2.5 型
  • 3.5.2.2 列挙子指定子

キーワード

enum

関連項目

C++ ドキュメント for 列挙型宣言