存儲類型和一些關(guān)鍵字

參考:C Storage Classes
iOS定義靜態(tài)變量漱受、靜態(tài)常量络凿、全局變量
iOS開發(fā)——OC篇&常用關(guān)鍵字的使用與區(qū)別
iOS 宏(define)與常量(const)的正確使用

一、C語言的存儲類型

在C語言中昂羡,程序內(nèi)變量或函數(shù)的作用域和壽命是由其存儲類確定的絮记。每個變量都具有生存周期,或存儲其值得上下文虐先。方法怨愤,同變量一樣,也存在蛹批,或可見于撰洗,一個特殊的范圍里,這就決定了哪一部分能夠知道且能夠訪問它們腐芍。

C里有四種存儲類:

  • auto
  • register
  • static
  • extern
1差导、auto

很有可能你從來沒見過這個關(guān)鍵字。這是因為auto是默認(rèn)存儲類猪勇,因此通常并不需要顯式的使用设褐。

當(dāng)運(yùn)行到程序塊的時候,auto類型的變量能自動分配內(nèi)存,并且在該程序塊運(yùn)行完成時釋放助析。 訪問auto變量僅限于聲明它的block犀被,以及任何嵌套block內(nèi)。

2外冀、register

大多數(shù)OC程序員可能也不熟悉register寡键,因為它沒有被廣泛的使用在NS世界里。

register行為就像auto锥惋,但不同的是它們不是被分配到堆棧中昌腰,它們被存儲在一個寄存器里开伏。

寄存器能比內(nèi)存提供更快的訪問速度膀跌,但由于內(nèi)存管理的復(fù)雜性,把變量放在寄存器中并不能保證程序變得更快固灵。事實上,很可能由于在寄存器上占用了不必要的空間而最終被放緩執(zhí)行。使用寄存器實際上只是一個給編譯器存儲變量的建議捏卓,實現(xiàn)時可以選擇是否遵從這一點逗栽。

寄存器在OC不夠普及其實挺好的:最好還是不要使用它,因為比起其他任何明顯的方式加快應(yīng)用程序仍秤,它更容易引起讓人更加頭疼的結(jié)果熄诡。

3、static

作為關(guān)鍵字诗力,static被以很多不同的凰浮,不兼容的方式使用,因此要弄清楚每一個實例到底是什么意思可能會造成混淆苇本。

  • 方法或函數(shù)內(nèi)部的一個static變量保留其調(diào)用之前的值袜茧。

  • 全局聲明的一個static變量可以被任何函數(shù)或方法調(diào)用,只要這些方法出現(xiàn)在跟static變量同一個文件中瓣窄。這同樣適用于static方法笛厦。

    靜態(tài)單例

OC中一個常見的模式是靜態(tài)單例,在這個case里俺夕,一個靜態(tài)聲明的變量被初始化裳凸,并在任何一個函數(shù)或者類方法中被返回。 dispatch once 用于保證變量初始化在一個線程安全的方式下 只 發(fā)生一次:

+ (instancetype)sharedInstance {
  static id _sharedInstance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
      _sharedInstance = [[self alloc] init];
  });

  return _sharedInstance;
}

單例模式對于創(chuàng)建整個應(yīng)用程序共享的對象是很有用的劝贸,諸如HTTP客戶端或一個通知管理登舞,或創(chuàng)建過程很昂貴的對象,諸如格式化悬荣。

4菠秒、extern

當(dāng)static使得一個特定的文件中的函數(shù)和變量全局可見,extern則使它們對所有文件可見。

一般來說践叠,全局變量并不是一個好主意言缤。由于沒有如何及何時改變只的任何對extern有兩個常見和實際的用途。

全局字符串常量

任何時候禁灼,如果你的應(yīng)用程序要在一個公共文件頭部申明一個非自然語言的字符串常量管挟,都應(yīng)該將其聲明為外部字符串常量。尤其是在聲明諸如userInfo字典弄捕,NSNotification 名稱和 NSError 域的時候僻孝。

該模式是在公共頭文件里申明一個extern的NSSting*const,并在實現(xiàn)文件里定義該NSString * const:

//AppDelegate.h
extern NSString * const kAppErrorDomain;

//AppDelegate.m
NSString * const kAppErrorDomain = @"com.example.yourapp.error";

字符串的值并沒有特別需要注意的事情守谓,只要它是唯一的穿铆。使用字符串常量建立了嚴(yán)格的約束,用該常數(shù)變量來代替字符串文本值本身斋荞。

公共方法

一些API可能會想要公開曝光一些輔助方法荞雏。由于僅提供輔助而與具體狀態(tài)無關(guān)的考慮,用方法來封裝這些行為是一個很好的方式平酿,而且如果特別有用凤优,還可能值得使其全局可用。

//TransactionStateMachine.h
typedef NS_ENUM(NSUInteger, TransactionState) { TransactionOpened, TransactionPending, TransactionClosed,};extern NSString * NSStringFromTransactionState(TransactionState state);

//TransactionStateMachine.m
NSString * NSStringFromTransactionState(TransactionState state) { switch (state) { case TransactionOpened: return @"Opened"; case TransactionPending: return @"Pending"; case TransactionClosed: return @"Closed"; default: return nil; }}

理解任何事情其實都是去了解上下文蜈彼≈妫可能那些我們看到的很明顯且不證自明的東西,對所有那些沒有我們的參照系的人來說是未知的幸逆。我們無法真正了解和欣賞自己和他人的觀點及信息的差異或許使我們最根本的缺點棍辕。

這就是為什么,在我們構(gòu)建的邏輯0和1的宇宙中秉颗,我們?nèi)绱酥?jǐn)慎的區(qū)分上下文痢毒,并基于這些明確的規(guī)則上構(gòu)建我們的假設(shè)。C存儲類對于理解程序是如何運(yùn)行時必不可少的蚕甥。如果沒有他們哪替,我們的開發(fā)將如履薄冰。因此菇怀,需要謹(jǐn)慎對待這些簡單的規(guī)則凭舶,才能包含新新的編寫代碼。

二爱沟、iOS的內(nèi)存存儲區(qū)的劃分

  • 1帅霜、棧區(qū):棧區(qū)主要存放函數(shù)內(nèi)部定義的變量、數(shù)組呼伸。函數(shù)調(diào)用時身冀,開辟空間钝尸,函數(shù)執(zhí)行完畢,回收空間搂根,空間的開辟與回收有系統(tǒng)管理珍促。
  • 2、堆區(qū):堆區(qū)最大的特點:空間的開辟與釋放由開發(fā)人員手動管理剩愧。
  • 3猪叙、全局靜態(tài)區(qū):主要存放函數(shù)外部定義的全局變量以及靜態(tài)變量,空間一旦開辟仁卷,就不會回收穴翩,直到應(yīng)用程序執(zhí)行結(jié)束。
  • 4锦积、常量區(qū):存儲常量:整形常量芒帕、浮點型常量、字符串常量
  • 5充包、代碼區(qū):存放程序編譯之后生成的cpu指令副签。

三遥椿、OC中的一些關(guān)鍵字

1基矮、static
1.1 static變量只是在編譯時候進(jìn)行初始化,對于static變量冠场,無論是定義在方法體里面還是在方法體外面其作用域都一樣家浇。

我們經(jīng)常使用的UItableViewController里面,在定義UItableView的時候碴裙,模板會經(jīng)常使用以下代碼

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 
{
 
static NSString *CellIdentifier = @"Cell";
 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
 
return cell;
 
}

在上面定義了static變量钢悲,在編譯期間會對這個變量進(jìn)行初始化賦值,也就是說這個變量值要么為nil舔株,要么在編譯期就可以確定其值莺琳,一般情況下,只能用NSSrting或者基本類型载慈,并且這個變量只能在cellForRowAtIndexPath訪問惭等。這個和C語言里面的static的變量屬性一樣。

1.2 static變量也可以定義在.m的方法體外办铡。這樣所有的方法內(nèi)部都可以訪問這個變量辞做。但是在類之外是沒有辦法訪問的,也就是不能用 XXXClass.staticVar 的方式來訪問 staticVar變量寡具。相當(dāng)于static變量都是私有的秤茅。

如果.m文件和方法體里面定義了同名的static變量,那么方法體里面的實例變量和全局的static變量不會沖突童叠,在方法體內(nèi)部訪問的static變量和全局的static變量是不同的框喳。

@implementation IFoundAppDelegate
 
static NSString * staticStr  = @"test";
 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 
{
 
static NSString * staticStr  = @"test2";
 
NSLog(@"the staticStr is %@ -- %d",staticStr,[staticStr hash]);
 
}
 
- (void)applicationWillResignActive:(UIApplication *)application
 
{
 
NSLog(@"the staticStr is %@ -- %d",staticStr,[staticStr hash]);
 
}

以上兩個static變量是兩個不同的變量,在didFinishLaunchingWithOptions方法內(nèi)部,訪問的是方法體內(nèi)部定義的staticStr變量五垮,在applicationWillResignActive方法體里面撰豺,訪問的是全局定義的staticStr變量∑从啵可以通過日志打印其hash來進(jìn)行確認(rèn)兩個變量是否一樣污桦。

2、const和define
2.1匙监、當(dāng)我們想全局共用一些數(shù)據(jù)時凡橱,可以用宏、變量亭姥、常量

宏:

#define HSCoder @"漢斯哈哈哈"

變量:

NSString *HSCoder = @"漢斯哈哈哈";

常量:

//四種寫法:
static const NSString *HSCoder = @"漢斯哈哈哈";
const NSString *HSCoder = @"漢斯哈哈哈";
NSString const *HSCoder = @"漢斯哈哈哈";
NSString * const HSCoder = @"漢斯哈哈哈";

思考:宏與常/變量的選擇稼钩?

  • 宏:只是預(yù)處理器里進(jìn)行文本替換,沒有類型达罗,不做任何類型檢查坝撑,編譯器可以對相同的字符串進(jìn)行優(yōu)化。只保存一份到 .rodata 段粮揉。甚至有相同后綴的字符串也可以優(yōu)化巡李,你可以用GCC 編譯測試,"Hello world" 與 "world" 兩個字符串扶认,只存儲前面一個侨拦。取的時候只需要給前面和中間的地址,如果是整形辐宾、浮點型會有多份拷貝狱从,但這些數(shù)寫在指令中。占的只是代碼段而已叠纹,大量用宏會導(dǎo)致二進(jìn)制文件變大季研。
  • 變量:共享一塊內(nèi)存空間,就算項目中N處用到誉察,也不會分配N塊內(nèi)存空間与涡,可以被修改,在編譯階段會執(zhí)行類型檢查冒窍。
  • 常量:共享一塊內(nèi)存空間递沪,就算項目中N處用到,也不會分配N塊內(nèi)存空間综液,可以根據(jù)const修飾的位置設(shè)定能否修改款慨,在編譯階段會執(zhí)行類型檢查。
2.2 常量區(qū)分

全局常量: 不管你定義在任何文件夾谬莹,外部都能訪問檩奠。

const NSString *HSCoder = @"漢斯哈哈哈";

局部常量:用static修飾后桩了,不能提供外界訪問

static const NSString *HSCoder = @"漢斯哈哈哈";

ps :static經(jīng)常用到.m文件中,如果是.h文件定義的全局變量埠戳,在別的文件中井誉,引入這個頭文件,也是可以訪問這個變量的整胃。

2.3const修飾位置不同颗圣,代表什么?
1.const NSString *HSCoder = @"漢斯哈哈哈";
"*HSCoder"不能被修改屁使, "HSCoder"能被修改

2.NSString const *HSCoder = @"漢斯哈哈哈";
"*HSCoder"不能被修改在岂, "HSCoder"能被修改

3.NSString * const HSCoder = @"漢斯哈哈哈";
"HSCoder"不能被修改,"*HSCoder"能被修改


結(jié)論:const右邊的總不能被修改

驗證:

1.png
2.png
3.png
4.png
image.png

所以一般我們定義一個常量又不想被修改應(yīng)該這樣:

NSString * const HSCoder = @"漢斯哈哈哈";

一般項目中蛮寂,定義全局常量蔽午,會寫在獨立文件中

5.png
6.png

訪問:

導(dǎo)入頭文件


7.png

訪問常量


8.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市酬蹋,隨后出現(xiàn)的幾起案子及老,更是在濱河造成了極大的恐慌,老刑警劉巖范抓,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骄恶,死亡現(xiàn)場離奇詭異,居然都是意外死亡尉咕,警方通過查閱死者的電腦和手機(jī)叠蝇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門璃岳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來年缎,“玉大人,你說我怎么就攤上這事铃慷〉ノ撸” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵犁柜,是天一觀的道長洲鸠。 經(jīng)常有香客問我,道長馋缅,這世上最難降的妖魔是什么扒腕? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮萤悴,結(jié)果婚禮上瘾腰,老公的妹妹穿的比我還像新娘。我一直安慰自己覆履,他們只是感情好蹋盆,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布费薄。 她就那樣靜靜地躺著,像睡著了一般栖雾。 火紅的嫁衣襯著肌膚如雪楞抡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天析藕,我揣著相機(jī)與錄音召廷,去河邊找鬼。 笑死账胧,一個胖子當(dāng)著我的面吹牛柱恤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播找爱,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼梗顺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了车摄?” 一聲冷哼從身側(cè)響起寺谤,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吮播,沒想到半個月后变屁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡意狠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年粟关,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片环戈。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡闷板,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出院塞,到底是詐尸還是另有隱情遮晚,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布拦止,位于F島的核電站县遣,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汹族。R本人自食惡果不足惜萧求,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望顶瞒。 院中可真熱鬧夸政,春花似錦、人聲如沸搁拙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酪碘,卻和暖如春朋譬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背兴垦。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工徙赢, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人探越。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓狡赐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钦幔。 傳聞我的和親對象是個殘疾皇子枕屉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法鲤氢,內(nèi)部類的語法搀擂,繼承相關(guān)的語法,異常的語法卷玉,線程的語...
    子非魚_t_閱讀 31,599評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理哨颂,服務(wù)發(fā)現(xiàn),斷路器相种,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 注:這是第三遍讀《C語言深度解剖》威恼,想想好像自從大學(xué)開始就沒讀完過幾本書,其中譚浩強(qiáng)的那本《C語言程序設(shè)計(第四版...
    HavenXie閱讀 1,717評論 1 6
  • 閱讀及筆記時間:2016年12月4日寝并,20:00-23:00箫措;3小時; 閱讀書本:《菊與刀》食茎;作者:【美】魯思·本...
    時空山莊閱讀 402評論 0 6
  • 作為中國最大的搜索引擎别渔,同時也是 BAT 中最臭名昭著的產(chǎn)品,百度搜索惧互,我們每天都在使用哎媚,雖然已經(jīng)有無數(shù)文章和你講...
    塵飛FlyingDust閱讀 1,698評論 5 9