在專案的預編譯頭文件(PCH)中定義全域常量是常見需求。許多開發者習慣用 #define 宏,但細閱 Apple 官方頭文件會發現,它們大量使用 const 修飾的變量。本文深度解析兩者差異,並給出工程級最佳實踐方案。
const 在 C/Objective-C 中的核心語法const int age1 = 20; int const age2 = 30; // 效果完全相同,age1/age2 為唯讀常量
int age = 20, num = 30; const int *p1 = &age; // *p1 唯讀,p1 可指向別處 int const *p2 = &age; // 同上 int *const p3 = &age; // p3 指針本身不可變,*p3 可修改 // int *const p3 = &age; p3 = # // 編譯錯誤 // *p3 = 30; // 正確
| 維度 | #define 宏 | const 變量 |
|---|---|---|
| 處理階段 | 預處理器(編譯前) | 編譯器(編譯期) |
| 記憶體佔用 | 每次使用展開,可能產生多份拷貝 | 全程僅一份記憶體,所有引用共享 |
| 類型安全 | 無類型,純文本替換 | 完整類型系統,編譯期檢查 |
| 除錯可見性 | 符號表無宏名,除錯器見不到 | 符號表保留變量名,可直接 Watch |
| 作用域控制 | 無作用域,全域汙染風險 | 遵循 C 語言作用域規則 |
建立專用常量類,.h 用 extern 宣告,.m 定義實體:
// ZYConst.h #import// 通知名稱常量 extern NSString *const ZYEmotionDidSelectNotification; extern NSString *const ZYSelectEmotionKey; extern NSString *const ZYEmotionDidDeleteNotification; // ZYConst.m #import "ZYConst.h" NSString *const ZYEmotionDidSelectNotification = @"ZYEmotionDidSelectNotification"; NSString *const ZYSelectEmotionKey = @"ZYSelectEmotionKey"; NSString *const ZYEmotionDidDeleteNotification = @"ZYEmotionDidDeleteNotification";
在 PCH 中僅需 #import "ZYConst.h",全專案即可直接使用,享受單一記憶體實體、類型安全、除錯友好三重優勢。
const 要求初始化值為編譯期常量,無法用於涉及運算的場景: