現實世界中許多變量的取值被限定在有限集合內:一周七天、十二個月、錯誤碼、狀態機狀態等。若用 int 或 char 表示,編譯器無法約束取值範圍,代碼可讀性也差。枚舉(enum)正是為此而生:在類型系統層面約束取值集合,同時賦予語義化名稱。
enum EnumName {
VAL1, VAL2, VAL3, ...
};
enum Weekday {
SUN, MON, TUE, WED, THU, FRI, SAT
};
枚舉元素(SUN..SAT)是常量,而非變量,不可修改。編譯器默認從 0 開始按序賦值:SUN=0, MON=1, ..., SAT=6。也可顯式指定:
enum Color { RED=1, GREEN=2, BLUE=4 }; // 位掩碼風格
enum Status { ERR=-1, OK=0, PENDING=10 };
// 1. 先定義後聲明
enum Weekday { SUN, MON, TUE, WED, THU, FRI, SAT };
enum Weekday today, tomorrow;
// 2. 定義同時聲明
enum Weekday { SUN, MON, TUE, WED, THU, FRI, SAT } today, tomorrow;
// 3. 匿名枚舉直接聲明
enum { SUN, MON, TUE, WED, THU, FRI, SAT } today, tomorrow;
| 操作 | 正確示例 | 錯誤示例 | 說明 |
|---|---|---|---|
| 賦值 | today = MON; | today = 1; | 只能賦枚舉常量,不可直接賦整數(類型不匹配) |
| 強制轉換 | today = (enum Weekday)2; | 必須顯式轉型,相當於 today = TUE; | |
| 比較 | if (today == MON) | 支援 == != 等關係運算 | |
| 輸出 | printf("%d", today); | printf("%s", today); | 只能輸出底層整數值,無內建字符串化 |
| switch | switch(today) { case MON: ... } | 完美適配 switch-case |
#include <stdio.h>
int main() {
enum Month { JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
enum Month m;
for (m = JAN; m <= DEC; m = (enum Month)(m + 1)) {
printf("%2d ", m);
}
printf("\n");
// 配合 switch 輸出中文
for (m = JAN; m <= DEC; m = (enum Month)(m + 1)) {
switch (m) {
case JAN: printf("一月 "); break;
case FEB: printf("二月 "); break;
// ... 其餘月份
default: break;
}
}
return 0;
}
int、unsigned int 或 signed/unsigned char/short/long,由編譯器根據取值範圍選擇。sizeof(enum Weekday) 通常等於 sizeof(int)(4 字節)。case 'MON': 是錯的。switch 使用時,編譯器可檢測是否覆蓋所有情況(需開啟 -Wswitch-enum)。