枚举
枚舉類型 是獨立的類型,其值為包含所有其顯示命名的常量(枚舉常量)的底層類型 的值。
語法
枚舉類型在聲明文法中以跟隨的枚舉說明符 作為類型說明符 聲明:
enum 屬性聲明符序列 (可選) 標識符 (可選) { 枚舉項列表 }
|
(1) | ||||||||
enum 屬性聲明符序列 (可選) 標識符 (可選) : 類型 { 枚舉項列表 }
|
(2) | (C23 起) | |||||||
其中枚舉項列表 是枚舉項 的逗號分隔列表(允許尾隨的逗號)(C99 起),每個枚舉項 擁有形式:
| 枚舉常量 屬性聲明符序列 (可選) | (1) | ||||||||
枚舉常量 屬性聲明符序列 (可選) = 常量表達式
|
(2) | ||||||||
其中
| 標識符, 枚舉常量 | - | 由此聲明引入的標識符 |
| 常量表達式 | - | 整數常量表達式,其值可以以 int 類型的值表示。(C23 前)若枚舉具有固定底層類型,則其可以表示為類型 的值(C23 起)
|
| 屬性聲明符序列 | - | (C23)可選的屬性列表,
|
與結構體或聯合體一樣,引入枚舉類型和一或多個枚舉常量的聲明亦可聲明一或多個該類型的對象,或從該類型派生的類型的對象。
enum color_t {RED, GREEN, BLUE} c = RED, *cp = &c;
// 引入类型 enum color_t
// 整数常量 RED 、 GREEN 、 BLUE
// 对象 c 拥有类型 enum color_t
// 对象 cp 的类型为指向 enum color_t 的指针
解釋
每個出現於枚舉說明符體中的枚舉常量 會成為 int 類型的(C23 前)整數常量,並處於包圍它的作用域中,而且在凡要求整數常量處可用(例如,作為 case 標號或非 VLA 數組大小)。
|
在處理枚舉項列表中的每個枚舉常量過程中,枚舉常量的類型應當為:
當被加的前一個枚舉常量為有符號整數類型時,選用有符號整數類型。當被加的前一個枚舉常量為無符號整數類型時,選用無符號整數類型。如果不存在前述可以表示新值的合適的有符號整數類型,則該枚舉沒有有能力表示其所有值的類型。 |
(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;
}
若枚舉常量 後隨= 常量表達式 ,則其值為該常量表達式的值。若枚舉常量 沒有後隨=常量表達式 ,則其值是比同一枚舉中前一枚舉項的值大一的值。首個枚舉項(若它不用 = 常量表達式 )的值是零。
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; // 错误: color 不在通常命名空间中
typedef enum color color_t;
color_t x = GREEN; // OK
每個無固定底層類型的(C23 起)枚舉類型與如下之一兼容:char、有符號整數類型或無符號整數類型(不包括 bool 和位精確整數類型)(C23 起)。對於任何枚舉類型,哪一個類型是兼容的是實現定義的,但無論是那種類型,都必須有足以表示該枚舉中所有枚舉項的值。對於所有具有固定底層類型的枚舉,枚舉的類型均與枚舉的底層類型兼容。(C23 起)
|
沒有固定底層類型的枚舉類型,在其完成處枚舉成員的類型為:
|
(C23 起) |
所有枚舉均有底層類型。可以通過用 enum-類型說明符 顯式指定底層類型,並作為其固定底層類型。如果未顯示指定,則其底層類型為枚舉的兼容類型,它為有符號或無符號的整數類型或 char。
|
(C23 起) |
枚舉類型是整數類型,從而可以用於任何其他整數類型能用之處,包括隱式轉換和算術運算符。
enum { ONE = 1, TWO } e;
long n = ONE; // 提升
double d = ONE; // 转换
e = 1.2; // 转换,e 现在是 ONE
e = e + 1; // e 现在是 TWO
註解
不同於 struct 或 union , C 中沒有 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; }; // 也 OK
自 C23 起也可用 constexpr 來達成相同目的:
constexpr int TEN = 10;
struct S { int x : TEN; }; // 也 OK
另外,由於 C 中結構體或聯合體不建立其作用域,可以在前者的成員說明中引入枚舉類型及其枚舉常量,而之後其作用域與前者相同。
struct Element
{
int z;
enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// 类型 enum 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 Types (第 39 頁)
- 6.7.2.2 Enumeration specifiers (第 107-112 頁)
- C17 標準(ISO/IEC 9899:2018):
- 6.2.5/16 Types (第 32 頁)
- 6.7.2.2 Enumeration specifiers (第 84-85 頁)
- C11 標準(ISO/IEC 9899:2011):
- 6.2.5/16 Types (第 41 頁)
- 6.7.2.2 Enumeration specifiers (第 117-118 頁)
- C99 標準(ISO/IEC 9899:1999):
- 6.2.5/16 Types (第 35 頁)
- 6.7.2.2 Enumeration specifiers (第 105-106 頁)
- C89/C90 標準(ISO/IEC 9899:1990):
- 3.1.2.5 Types
- 3.5.2.2 Enumeration specifiers
關鍵詞
參閱
枚舉聲明的 C++ 文檔
|