iOS 經常使用關鍵字 static、const、 extern、define

經常使用關鍵字 static、const、 extern、define

static

引用[Effectuve Objective-C] static 修飾則意味着該變量僅在定義此變量的編譯單元中可見, 不會致使其餘單元重複致使命名衝突, 當編譯器編譯到此單元時, 就會輸出一份 "目標文件"(object file)bash

其可用於修飾常量變量或函數, 延長其生命週期, 被修飾的數據類型會保存到 bbs段(靜態區) 中, 內存由編譯器分配, 通常隨程序結束後清除釋放, 被修飾的數據類型, 系統只會爲其分配一次內存地址, 因此用於修飾數據類型時, 無論執行多少次, 被修飾的數據類型只會初始化一次。框架

  • 修飾全局變量
static NSTimeInterval kAnimationDuration = 0.3; 
@implementation JSDAnimationVC
複製代碼

在全局變量前加static, 全局變量就被定義成爲一個全局靜態變量(全局變量和靜態全局變量的生命週期是同樣的, 都是在堆中的靜態區, 在整個工程執行期間內一直存在) 而靜態全局變量則限制了其做用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。函數

特色以下:學習

  1. 存儲區:靜態存儲區沒變(靜態存儲區在整個程序運行期間都存在)。
  2. 做用域:全局靜態變量在聲明他的文件以外是不可見的。準確地講從定義之處開始到文件結尾。非靜態全局變量的做用域是整個源程序(多個源文件能夠共同使用)。

相對全局變量優勢:優化

做用域只在原文件內, 不會影響到其餘文件, 同理也不受其餘文件影響。 避免其餘文件重定義致使命名衝突。動畫

  • 修飾局部變量
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    for (NSInteger i = 0; i < 100; i++) {
        static int count = 10;
        count++;
    };
}
複製代碼
  1. 延長局部變量的生命週期, 程序結束纔會銷燬。
  2. 局部變量只會生成一分內存, 無論方法執行多少次, 其只會初始化一次。
  3. 存儲區域從移動到bbs
  • 修飾函數

與修飾變量做用同理。spa

const

const 表示常量, 被修飾以後的數據類型, 由變量轉爲常量, 其不能夠被修改, 在編譯階段會執行檢查, 其存儲區域位於常量區, 經常使用於配合 static 或 extern 使用。翻譯

  • 修飾全局靜態變量
static const NSTimeInterval kAnimationDuration = 0.3; 
@implementation JSDAnimationVC
複製代碼

上面的全局變量表示的是動畫執行時間, 雖然其不會受外部文件影響, 可是在內部文件是能夠直接對其進行從新賦值的, 這明顯不符合咱們需求, 在變量前面加上關鍵字 const便可.指針

kAnimationDuration 全局靜態變量被修飾後變成全局靜態常量, 其內存區域由 bbs移動到常量區code

  • 修飾全局變量

用法:

extern NSString* const JSDLoginManagerDidLoginNotification;
@interface JSDLoginManagerVC : ViewController
@end
NSString * const JSDLoginManagerDidLoginNotification = @"JSDLoginManagerDidLoginNotification";
@implementation JSDCrashVC
複製代碼

包括在 .h .m 文件內聲明的變量, 都屬於全局變量, 除非 @implementation 做用域內聲明的, 因此這些全局變量都有可能由外部進行訪問, 並修改致使獲取不到意料的結果, 咱們可使用 const 來對其限制。 當外部文件訪問時須要使用關鍵字 extern 而且指明常量聲明的類型來使用, 不然編譯器默認以 int 類型來處理。應該是與運行時有關。

  • 修飾局部變量

在**@implementation** 實現中, 方法實現內進行聲明 主要用於修飾 C 或 OC 數據類型, 使聲明的變量定義爲常量。 下面列舉下三種修飾寫法, 致使不一樣的結果。

const NSString * name = @"Jersey";
使 *name 指針地址不可變, 實際指向內容不受影響, 修改指針地址編譯器報錯。
NSString const * name = @"Jersey";
同上面寫法一致, 修飾了 name 指針地址使其不可變
NSString * const name = @"Jersey";
使 *name 指針指向內容不可變, 指針地址不受影響, 修改內容則編譯報錯。
複製代碼

總結: const 修飾其後面內容

extern

這個單詞翻譯過來是"外面的, 外部的"。 顧名思義, 它的做用是聲明外部全局變量。這裏須要特別注意 extern 只能聲明, 不能用於實現。 當使用 extern 來聲明變量時, 其會先在編譯單元內部進行查找, 若是沒有則繼續到外部進行查找, 若是缺乏實現而且使用到了此數據時會致使編譯不經過。

用法:

  • 使用其來聲明供外部使用。

最經常使用也是最多見的實現通常是, .h 用 extern 修飾可供外部使用, .m 實現

extern NSString* const JSDLoginManagerDidLoginNotification;
@interface JSDLoginManagerVC : ViewController
@end
NSString * const JSDLoginManagerDidLoginNotification = @"JSDLoginManagerDidLoginNotification";
@implementation JSDCrashVC
複製代碼
  • 使用其來聲明引用外部全局變量等。

這種比較少見, 好比使用三方庫時, 三方庫定義了全局變量或常量, 可是並無在 .h 用 extern 修飾其聲明出來, 這時候若是咱們想要去使用時, 能夠直接在 .h 對其進行修飾便可直接使用

extern NSString* const JSDLoginManagerDidLoginNotification;
@interface JSDManager : NSObject
@end
複製代碼

主要配合關鍵字 const 使用, 相似用法一。

define

簡單說其實就是字符替換, 系統會在調用的地方進行文本替換, 可用於修飾數據, 函數, 結構體, 方法等, 系統不會對其作類型檢查。

引用喵神**[宏定義的黑魔法]**原文: 宏定義在C系開發中能夠說佔有舉足輕重的做用。底層框架自沒必要說,爲了編譯優化和方便,以及跨平臺能力,宏被大量使用,能夠說底層開發離開define將步履維艱。而在更高層級進行開發時,咱們會將更多的重心放在業務邏輯上,彷佛對宏的使用和依賴並很少。可是使用宏定義的好處是不言自明的,在節省工做量的同時,代碼可讀性大大增長。若是想成爲一個能寫出漂亮優雅代碼的開發者,宏定義絕對是必不可少的技能

得益於宏定義的高效與靈活性, 在不少底層系統中大量被使用, 其玩法也很是的多, 感興趣的能夠參考喵神這篇文章

宏定義的黑魔法 - 宏菜鳥起飛手冊

define 與 const 選擇

宏定義是在預編譯期間處理, 在使用時系統直接進行的方法替換, 靜態變量等則是在編譯期間進行的。 宏定義不會系統不會作編譯檢查, 因此類型錯誤也能經過編譯, const 則會作編譯檢查。 能顯式的聲明數據類型, 而且不會出現本身定義的宏被其餘人員更換,致使出現難以排查的 Bug。 不過宏不只能對數據類型進行定義, 還能對函數, 結構體, 方法等進行定義相對比起常量來講做用會更多一些。

總結

  1. 編譯時刻:宏是預編譯, const是編譯階段
  2. 編譯檢查:宏不作檢查, 有錯誤不會提示, const會檢查, 有錯誤會提示
  3. 宏的優勢:高效,靈活,可用於替換各類 函數,方法,結構體,數據等;
  4. 宏的缺點:因爲在預編譯期間完成, 大量使用宏, 容易形成編譯時間久
  5. const優勢:編譯器一般不爲普通 const 常量分配存儲空間, 而是將它們保存在符號表中, 這使得它成爲一個編譯期間的常量, 沒有了存儲與讀內存的操做, 使得它的效率也很高, 至關於宏更加高效, 而且容錯率很低。
  6. const缺點:const 能定義的內容很是有限, 只能用於定義常量
  7. 宏定義所定義的生命週期與所在的載體的生命週期有關
  8. const修飾具備就近性, 即 const 後面的參數是不可變的, const修飾的參數具備只讀性, 若是試圖修改, 編譯器就會報錯
  9. 蘋果官方不推薦咱們使用宏, 推薦使用const常量

建議: 在實際開發中, 對於能使用常量定義完成的, 儘可能使用常量能實現, 而不要考慮使用 宏。 讀 [Effective Objective-C] 第四條: 多用類型常量, 少用 #define 與處理指令, 蘋果也推薦咱們在開發中儘可能使用常量。

最後

但願此篇文章對您有所幫助,若有不對的地方,但願你們能留言指出糾正。謝謝!!!!! 學習的路上,與君共勉!!!

本文原創做者:Jersey. 歡迎轉載,請註明出處和本文連接

參考

OC中關鍵字extern、static、const探究

如何正確使用const,static,extern

iOS 宏(define)與常量(const)的正確使用

宏定義的黑魔法 - 宏菜鳥起飛手冊

相關文章
相關標籤/搜索