名稱空間
變體
操作

列舉

來自 cppreference.com
< c‎ | 語言

列舉型別是一種獨特的型別,其值為其底層型別(見下文)的值,包括顯式命名的常量(列舉常量)的值。

目錄

[編輯] 語法

列舉型別在宣告語法中,使用以下列舉說明符作為型別說明符進行宣告:

enum 屬性說明符序列 (可選) 識別符號 (可選) { 列舉器列表 } (1)
enum 屬性說明符序列 (可選) 識別符號 (可選) : 型別 { 列舉器列表 } (2) (自 C23 起)
1) 宣告一個沒有固定底層型別的列舉。
2) 宣告一個具有固定底層型別型別的列舉。

其中列舉器列表是一個逗號分隔的列表(允許尾隨逗號)(C99 起),每個列舉器的形式為:

列舉常量 屬性說明符序列 (可選) (1)
列舉常量 屬性說明符序列 (可選) = 常量表達式 (2)

其中

識別符號列舉常量 - 由該宣告引入的識別符號
常量表達式 - 整數常量表達式 其值可表示為int型別的值(C23 前)如果列舉具有固定底層型別,則表示為型別的值(C23 起)
屬性說明序列 - (C23)屬性的可選列表,
  • 如果出現在enum之後,則應用於整個列舉,
  • 如果出現在列舉常量之後,則應用於列舉器

結構體聯合體一樣,引入列舉型別和一個或多個列舉常量的宣告也可以宣告該型別或其派生型別的一個或多個物件。

enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// introduces the type enum color
// the integer constants RED, GREEN, BLUE
// the object c of type enum color
// the object cp of type pointer to enum color

[編輯] 解釋

出現在列舉說明符體中的每個列舉常量都成為封閉作用域中的整型常量,其型別為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;
}

如果列舉常量後跟= 常量表達式,則其值為該常量表達式的值。如果列舉常量後沒有跟= 常量表達式,則其值為同一列舉中前一個列舉器值加1。第一個列舉器(如果它不使用= 常量表達式)的值為零。

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

如果使用識別符號本身,它將成為標籤名稱空間中列舉型別的名稱,並且需要使用關鍵字enum(除非透過typedef將其引入普通名稱空間)。

enum color { RED, GREEN, BLUE };
enum color r = RED; // OK
// color x = GREEN; // Error: color is not in ordinary name space
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; // promotion
double d = ONE; // conversion
e = 1.2; // conversion, e is now ONE
e = e + 1; // e is now TWO

[編輯] 注意

結構體聯合體不同,C中沒有前向宣告的列舉。

enum Color; // Error: no forward-declarations for enums in C
enum Color { RED, GREEN, BLUE };

列舉允許以比#define更方便和結構化的方式宣告命名常量;它們在偵錯程式中可見,遵守作用域規則,並參與型別系統。

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

enum { TEN = 10 };
struct S { int x : TEN; }; // also OK

自 C23 起,constexpr 可用於相同的目的。

constexpr int TEN = 10;
struct S { int x : TEN; }; // also OK

此外,由於結構體聯合體在 C 中不建立自己的作用域,列舉型別及其列舉常量可以在前者的成員規範中引入,其作用域與前者的作用域相同。

struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
 
// type enum State and its enumeration constants stay visible here, e.g.
void foo(void)
{
    enum State e = LIQUID; // OK
    printf("%d %d %d ", e, oxygen.state, PLASMA); // prints 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 標準 (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++ 文件,關於列舉宣告