static變數詳解

2021-07-10 17:33:10 字數 3962 閱讀 3168

oc中經常用到單例。建立乙個單例的方法是這樣的(這裡隨便舉了乙個自己寫過的單例作為示例):

+ (instancetype)shareinstance);

return cookiehelper;

}

static iccookiehelper *cookiehelper = nil;
由於shareinstance方法會被多次呼叫,每次執行該方法,上面語句呼叫一次(在我未搞清楚static的作用之前我是這麼認為的),cookiehelper變數似乎又被重新定義了,且無初始值。但是賦值語句只執行一次啊,這樣一來cookiehelper不就是nil了!!一下子就懵逼了。我知道肯定是這個static耍了什麼把戲,於是開始查資料…

變數,包括區域性變數和全域性變數,又根據有無static修飾,分為靜態變數和非靜態變數。因此就有了非靜態區域性變數、靜態區域性變數、非靜態全域性變數、靜態全域性變數。但不管怎樣,都是變數沒的說!因此先來說說變數的所有的共性:生命週期。

乙個變數,其生命週期無非從建立開始到撤銷結束。其中的相關概念包括變數定義、初始化、賦值。

初始化:變數定義之後首次賦值

賦值:替換變數所在記憶體的內容

下面**對變數的使用過程做了測試,列印結果符合預期

int a;                  //定義乙個int變數,系統為其分配記憶體位址,但變數值是不確定的

nslog(@"%d",a); //乙個不確定數

nslog(@"%p",&a); //變數位址

nslog(@"********");

static

int *b; //定義乙個指標變數,系統為指標變數分配記憶體位址,該位址存放指標變數的位址,並不是變數本身所代表的位址,而指標變數本身所代表的位址是乙個空位址(空指標)。這裡把指標變數看成是普通變數就能理解為什麼變數本身值是空的了。

nslog(@"%p",b); //指標變數本身值為0x0

nslog(@"%p",&b); //指標變數位址(並非變數本身所代表的位址,而是存放指標變數的位址)

nslog(@"********");

a = 10; //對普通變數a賦值

nslog(@"%d",a); //10

nslog(@"%p",&a); //a的位址沒有改變

nslog(@"********");

b = &a; //對指標變數b賦值,把a的位址賦給b

nslog(@"%p",b); //&a

nslog(@"%p",&b); //b的位址沒有改變

nslog(@"********");

myobject *myobject; //定義乙個物件,物件是乙個指標變數

nslog(@"%@",myobject); //指標變數所指向的值為空 (null)

nslog(@"%p",myobject); //指標變數本身值為0x0

nslog(@"%p",&myobject); //指標變數的位址 0x7fff5fbff828

myobject = [[myobject alloc]init]; //指標變數初始化

nslog(@"%@",myobject); //

nslog(@"%p",myobject); //0x100400110 的位址

nslog(@"%p",&myobject); //0x7fff5fbff828 0x100400110的位址

myobject = [[myobject alloc]init]; //重新賦值

nslog(@"%@",myobject); //指標所指的值改變

nslog(@"%p",myobject); //指標變數的值改變

nslog(@"%p",&myobject); //指標變數的位址不變

所謂靜態變數,即被static修飾的變數。沒有被static修飾的變數,稱之非靜態變數,又稱自動變數,事實上它預設被auto修飾。

區域性變數定義在乙個函式內部,生存範圍為變數定義所在函式或模組,以「」界定,該型別變數只能在函式(模組)內被呼叫。

非靜態區域性變數即變數即是區域性的,又是非靜態的。變數在定義的時候被建立,當程式執行出了函式(模組),變數就被撤銷。當下次再次呼叫該函式(模組)時,重新建立的變數和之前的那個沒有半毛錢關係。

靜態區域性變數在函式內定義,它的生存期為整個源程式,但是其作用域仍與自動變數相同,只能在定義該變數的函式內使用該變數。退出該函式後,儘管該變數還繼續存在,但不能使用它。

基本型別的靜態區域性變數若在說明時未賦以初值,則系統自動賦予0值。而對自動變數不賦初值,其值是不定的。

靜態變數在其生命週期中只能定義一次,即當乙個靜態區域性變數在乙個函式中被定義之後,下次再次呼叫該函式,定義語句將不再被呼叫!!終於知道為什麼oc的單例能那樣寫了,原來static修飾的變數只能被定義一次,之後就不再呼叫定義語句了!!又漲姿勢了!!不過雖然不能多次定義,多次賦值卻是可以的,因此靜態變數的值是可以變的!不變的是變數所在的記憶體位址!

根據靜態區域性變數的特點,可以看出它是一種生存期為整個源程式的變數。雖然離開定義它的函式後不能使用,但如果再次呼叫定義它的函式時,它又可繼續使用, 而且儲存了前次被呼叫後留下的值。 因此,當多次呼叫乙個函式且要求在呼叫之間保留某些變數的值時,可考慮採用靜態區域性變數。雖然用全域性變數也可以達到上述目的,但全域性變數有時會造成意外的***,因此仍以採用區域性靜態變數為宜。

非靜態全域性變數也屬於靜態儲存方式,因此它的生命週期也是整個程式的生命週期。

如果對於乙個變數,想讓它的作用於不侷限與當前函式,而是想在其他函式,甚至在其他檔案中都能使用改變,這時候就要把變數定義成全域性變數。注意如果定義成靜態型別的,那麼其作用於只限於當前檔案,不能別其他檔案所共享。

如何跨檔案使用非靜態全域性變數呢?下面做簡單示例:

#import "myfile.h"

int a = 10;

@implementation

myfile

@end

在myfile.m檔案中建立並初始化了乙個全域性變數,下面**在main.m檔案中通過extern關鍵字引用該變數

#import 

int main(int argc, const

char * argv)

成功在main.m檔案中引用了myfile.m中定義的全域性變數a。注意:這裡稱這個過程為引用是正確的,extern關鍵的作用就是引用乙個外部定義的全域性變數,並沒有定義乙個新的變數。不信的話在不同的地方引用同乙個變數,分別列印位址,會發現是同乙個位址,也就是說始終只有乙個變數,只是在不同的地方使用它罷了(因此在多執行緒環境中要小心使用)。

另外,無需在引用全域性變數的檔案中匯入定義全域性變數所在檔案的標頭檔案,全域性變數編譯時就被定義好了。事實上,如果在乙個.h問價中定義了乙個區域性變數,另乙個檔案中又匯入該檔案就會報重複錯誤,因此區域性變數的定義通常都放在.m檔案中。

首先靜態全域性變數肯定也屬於靜態儲存方式,生命週期為整個程式。另外靜態全域性變數與非靜態全域性變數的區別,其實前面以及說過了。兩個的唯一區別在於,非靜態全域性變數的作用域是整個工程,即在別的檔案中也可以引用;靜態全域性變數的作用範圍只限於當前檔案,在同一源程式的其他檔案中不能直接引用。因此要想在別的檔案中操作當前檔案的靜態全域性變數,只能在當前檔案中定義乙個介面函式。

把區域性變數改變為靜態變數後是改變了它的儲存方式即改變了它的生命週期。把全域性變數改變為靜態變數後是改變了它的作用域,限制了它的使用範圍。因此static 這個說明符在不同的地方所起的作用是不同的。

C語言static變數詳解

這篇objective c篇寫的不錯 static的作用 1.在其他檔案隱藏同名函式和全域性變數。未加static字首的全域性變數和函式都具有全域性可見性,意味著其它檔案也能訪問。如果加了static,就會對其它原始檔隱藏。利用這一特性可以在不同的檔案中定義同名函式和同名變數,而不必擔心命名衝突。對...

static靜態變數詳解

什麼是static靜態變數?以下為在c語言中的理解 靜態變數 型別說明符是static。靜態變數屬於靜態儲存方式,其儲存空間為記憶體中的靜態資料區 在靜態儲存區內分配儲存單元 該 區域中的資料在整個程式的執行期間一直占用這些儲存空間 在程式整個執行期間都不釋放 也可以認為是其記憶體位址不變,直到整個...

區域性靜態變數Static詳解

在區域性變數前加上 static 關鍵字,就成了靜態區域性變數。靜態區域性變數存放在記憶體的全域性資料區。函式結束時,靜態區域性變數不會消失,每次該函式呼叫 時,也不會為其重新分配空間。它始終駐留在全域性資料區,直到程式執行結束。靜態區域性變數的初始化與全域性變數類似 如果不為其顯式初始化,則c 自...