1、預處理定義常量
#define ElementSpacing16
通常會像上述定義常量。上述預處理命令會把源代碼中的 ElementSpacing 字符串替換成 16 。該預處理命令會把所有碰到的 ElementSpacing 全部替換成 16 。如果該指令聲明在某個頭文件中,那么引入該頭文件的代碼,所有的 ElementSpacing 都會被替換。
2、static const extern
static const double kMargin = 10.0;
這樣定義常量包含的類型信息,好處:清楚的描述了常量的含義。變量一定要同時用 static 和 const 來聲明,試圖修改 const 修飾的變量,編譯器就會報錯;static 修飾的變量僅在定義該變量的編譯單元中可見,作用域就是該編譯單元,如果不用 static 修飾,編譯器就會為該變量創建外部符號(external symbol)。如果其他編譯單元也聲明了該變量,編譯器就會報錯。
如果同時使用 static 和 const 聲明,常量帶有類型信息。編譯器不會創建符號,會像#define預處理指令一樣,把遇到的變量替換成常量值。
常用的命名方法:1.在實現文件之內 采用 字母 k 開頭;2.常量在類外部可見,通常以類名為前綴
常量的位置很重要。盡量避免在聲明文件內定義,因為常量名會相互沖突。
? ? ? ?1.如果不想公開某個常量,就定義在實現文件內。?
? ? ? ?2.對外公布某個常量。該常量需放在全局符號表中(globe symbol table)。
? ? ? ?3.命名需謹慎,因為放在全局符號表中。為避免沖突,最好使用與之相關的類名做前綴。
? ? ? ?4.該種定義方法優先使用#define。編譯器會確保常量值不變。預處理定義可能會被他人隨意更改。
? ? ? ?5.最好不使用預處理定義常量。
聲明文件中 .h
extern NSString *const PageMap;
實現文件 .m
NSString *const PageMap = @"VALUE";
常量的定義是由右往左解讀,PageMap 是一個常量,該常量是指針,指向 NSString 對象。編譯器看到 extern 關鍵字,就會自動處理該常量了。傳遞給編譯器的消息就是,在全局符號表中會有一個 PageMap的符號,允許代碼使用該常量,當鏈接成二進制文件后一定會找到該常量。該常量必須要定義嗎,而且只能定義一次。編譯器會在數據段(data section)為它分配存儲空間。連接器會把該目標文件與其他目標文件鏈接,最終生成二進制文件,凡是用到 PageMap 全局符號的地方,鏈接器都能將其自動解析。
總結
1、不要使用預處理定義常量。定義出的常量不包含類型信息,編譯器只會在編譯前根據執行查找與替換操作。他人可重新定義常量值,這很危險。
2、在實現文件中(.m)使用 static const 修飾的變量,作用域就是.m 文件,不在全局符號表中。
3、在聲明文件中(.h)使用 extern 聲明全局變量,在相關 .m 文件中定義該變量值,該變量存于全局符號表中,命名時注意重名,最好添加類前綴加以區分。