| 維度 | 宏定義 #define | 枚舉類型 enum |
|---|---|---|
| 處理階段 | 預處理(文本替換) | 編譯(符號解析) |
| 作用域 | 文件級(從定義處到文件末或 #undef) | 塊級(遵循變量作用域規則) |
| 命名空間 | 無(全局文本替換) | 有(枚舉常量在標識符空間) |
| 類型安全 | 無 | 有(屬於枚舉類型) |
| 調試可見性 | 不可見(替換後無符號) | 可見(調試器識別枚舉名) |
| 取地址 | 不可 | 不可(純編譯期常量) |
| 值類型 | 任意文本 | 僅整數 |
// liba.h
#define MAX_SIZE 1024
// app_pub.h
#define MAX_SIZE 2048 // 衝突!
// main.c
#include "liba.h"
#include "app_pub.h" // 警告:重新定義,或靜默覆蓋導致邏輯錯誤
後果:包含順序決定最終值,極難排查。
#include "liba.h"
#ifdef MAX_SIZE
#undef MAX_SIZE
#endif
#include "app_pub.h"
static const 或 enum#define LIBA_MAX_SIZE 1024#undef(函數內部宏)inline 函數替代宏
void foo() {
enum Color { RED, GREEN, BLUE }; // 僅在 foo() 內可見
enum Color c = RED;
}
// 外部不可訪問 RED/GREEN/BLUE,無污染
c = RED 而非 c = 0| 宏定義 | 枚舉類型 |
|---|---|
| 代碼縮減(類函數宏) | 限制輸入域(類型安全) |
| 常量集中維護(易修改) | 語義分組(自文檔化) |
條件編譯 (#ifdef) | 編譯期計算 (switch case 優化) |
static const / constexpr (C++):有類型、有地址、作用域受控、調試可見enum (或 enum class C++):整數常量組、類型安全、無地址、調試友好#define:僅用於條件編譯、編譯期字符串拼接、平台差異隔離inline 函數
// 宏版(危險)
#define SQUARE(x) ((x)*(x))
SQUARE(i++) // 展開為 ((i++)*(i++)) → 未定義行為
// inline 版(安全)
static inline int square(int x) { return x * x; }
square(i++) // 正確計算
inline 有類型檢查、求值一次、調試可進入、編譯器自動決定是否內聯static inline 在頭文件安全定義(無重複符號)
typedef enum {
PERM_READ = 1 << 0, // 1
PERM_WRITE = 1 << 1, // 2
PERM_EXEC = 1 << 2, // 4
} Permission;
// 組合
int p = PERM_READ | PERM_WRITE; // 3
// 檢查
if (p & PERM_READ) ...
enum Color : int { RED, GREEN, BLUE }; // 指定底層類型
// 禁止隱式轉換為 int (需強制轉換)
宏定義是「預處理器的文本替換工具」,枚舉類型是「編譯器的類型安全常量系統」。**能用枚舉/const/inline 解決的,堅決不用宏**。宏的合法領地僅剩:#ifdef 條件編譯、__FILE__/__LINE__ 等內建宏、跨平台頭文件隔離、極少數字符串化(#)/連接(##)操作。現代 C 代碼庫中,宏佔比應< 5%,枚舉/常量/內聯函數佔比 > 95%。