引言:包括百度、中興在內(nèi)的很多公司都曾在筆試面試中出過下面題目
問題:全局變量和局部變量在內(nèi)存中是否有區(qū)別?如果有,是什么區(qū)別?
解析:有區(qū)別。全局變量保存在內(nèi)存的全局存儲區(qū)中,占用靜態(tài)的存儲單元;局部變量保存在棧中,只有在所在函數(shù)被調(diào)用時(shí)才動態(tài)地為變量分配存儲單元。
區(qū)分三種變量的特點(diǎn),如果只看聲明位置和訪問范圍,肯定不夠深刻的,需要進(jìn)一步理解在內(nèi)存中的不同。所以,這里我們來復(fù)習(xí)總結(jié)一下三種變量的特點(diǎn),區(qū)分鞏固基礎(chǔ)知識。
1. 全局變量
1.1 全局變量
- 函數(shù)外面聲明
- 可以跨文件訪問
- 可以在聲明時(shí)賦上初始值
- 如果沒有賦初始值,系統(tǒng)自動賦值為0
- 存儲位置:既非堆,也非棧,而是專門的【全局(靜態(tài))存儲區(qū)static】!
注意
例如,我們在A類中聲明和定義一個(gè)全局變量lastNum,類似如下
float lastNum;//僅聲明
float lastNum = 10.0;//聲明和定義
1.2 關(guān)于extern關(guān)鍵字
要注意的是,全局變量可以在許多地方聲明 為extern,但定義(賦初值)只能一次。而上面的代碼既聲明,也定義了一個(gè)全局變量lastNum。其中,定義的時(shí)候并不需要extern專門來修飾。倒是在其他不需要定義該全局變量的地方,需要extern來修飾該全局變量,聲明要調(diào)用外部變量了。
用法1
- 我們在B類想調(diào)用A類中聲明和定義的全局lastNum時(shí),并且B類也沒有導(dǎo)入A類,這時(shí),需要在B類中做
extern float lastNum;這樣聲明。這樣就告訴系統(tǒng),我要訪問其他文件中定義的這個(gè)全局變量了。注意點(diǎn):此時(shí),B類通過extern調(diào)用A類聲明的全局變量時(shí),B類中并不需要導(dǎo)入A類,例如類似import A.h等等。
A.m 中定義和聲明全局變量

image.png
B.m 中extern并調(diào)用全局變量

image.png
用法2.
- 我們在A.m文件中聲明和定義的全局lastNum時(shí),同時(shí)在A.h文件中做
extern float lastNum;這樣的聲明。在需要在B類中導(dǎo)入A類頭文件,就不需要在B類中專門做extern float lastNum;這樣的聲明了。這樣就告訴系統(tǒng),其它訪問A文件中定義的這個(gè)全局變量了,導(dǎo)入A類即可使用。
A.m 中聲明全局變量

image.png
A.h中extern全局變量

image.png
B.m中importA.m類并調(diào)用全局變量

image.png
2. 靜態(tài)變量
- 函數(shù)外面 或 內(nèi)部聲明(即可修飾原全局變量亦可修飾原局部變量)
- 僅聲明該變量的文件可以訪問
- 可以在聲明時(shí)賦上初始值
- 如果沒有賦初始值,系統(tǒng)自動賦值為0
- 存儲位置:既非堆,也非棧,而是專門的【全局(靜態(tài))存儲區(qū)static】!
static float lastNum;
static float lastNum = 10.0;
3. 局部變量(自動變量)
- 函數(shù)內(nèi)部聲明
- 僅當(dāng)函數(shù)執(zhí)行時(shí)存在
- 僅在本文件本函數(shù)內(nèi)可訪問
- 存儲位置:自動保存在函數(shù)的每次執(zhí)行的【棧幀】中,并隨著函數(shù)結(jié)束后自動釋放,另外,函數(shù)每次執(zhí)行則保存在【?!恐?/li>
- (float)caculateResult{
float a = 1.0;
float b = 2.0;
return a + b;
}
4. 內(nèi)存分區(qū)
堆和棧首先要清楚的是程序?qū)?nèi)存的使用分為以下幾個(gè)區(qū):
- 棧區(qū)(stack):由編譯器自動分配和釋放,存放函數(shù)的參數(shù)值,局部變量的值等。操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
- 堆區(qū)(heap):一般由程序員分配和釋放,若程序員不釋放,程序結(jié)束時(shí)可能由操作系統(tǒng)回收。與數(shù)據(jù)結(jié)構(gòu)中的堆是兩碼事,分配方式類似于鏈表。
- 全局區(qū)(static):全局變量和靜態(tài)變量存放在此。
- 文字常量區(qū):常量字符串放在此,程序結(jié)束后由系統(tǒng)釋放。
- 程序代碼區(qū):存放函數(shù)體的二進(jìn)制代碼。
5. 后面的話
- 與全局變量相比,靜態(tài)變量存儲位置一樣,聲明位置如果也一樣(函數(shù)外部),靜態(tài)變量這時(shí)跟全局變量有什么區(qū)別?就是為了限制訪問范圍,靜態(tài)變量僅當(dāng)前聲明該變量文件里面的代碼可以訪問。而全局變量可以同一工程跨文件訪問,可能會引起嚴(yán)重的混淆問題。
- 區(qū)分:內(nèi)存結(jié)構(gòu)(計(jì)算機(jī)系統(tǒng)原理)里面的【堆】跟數(shù)據(jù)結(jié)構(gòu)(算法與數(shù)據(jù)結(jié)構(gòu))里面的【堆】是兩回事
6. 拓展閱讀
- 進(jìn)一步理解函數(shù)調(diào)用與內(nèi)存中的棧與棧幀之間的關(guān)系,可以閱讀
http://www.itdecent.cn/p/e7a22923867f - 進(jìn)一步理解內(nèi)存的分區(qū),包括堆,棧,全局區(qū)等等,可以閱讀
http://www.itdecent.cn/p/a4335855154e