#include iostream.h
int p(int x)
{
static int y=1;
y=y+1;
return (x+y);}
int main()
{
cout<<p(1)<<endl;
cout<<p(2)<<endl;}
答案是3和5,為什么不是3和4呢?
c語(yǔ)言的static變量是在程序加載的時(shí)候就為之分配內(nèi)存的,一直到程序結(jié)束,而不像普通變量那樣函數(shù)執(zhí)行一次分配一次。所以當(dāng)?shù)谝淮螆?zhí)行p(1)的時(shí)候,y已經(jīng)加1了,下次執(zhí)行p(2)時(shí),y不會(huì)恢復(fù)成1,還是2;你就當(dāng)全局變量的功能處理就行,性能上有區(qū)別
-----------------------------------------------------------------------------------------------------------------------
以下是基礎(chǔ)知識(shí)點(diǎn)
-----------------------------------------------------------------------------------------------------------------------
1. static 變量
靜態(tài)變量的類型 說(shuō)明符是static。 靜態(tài)變量當(dāng)然是屬于靜態(tài)存儲(chǔ)方式,但是屬于靜態(tài)存儲(chǔ)方式的量不一定就是靜態(tài)變量。 例如外部變量雖屬于靜態(tài) 存儲(chǔ)方式,但不一定是靜態(tài)變量,必須由 static加以定義后才能成為靜態(tài)外部變量,或稱靜態(tài)全局變量。
2. 靜態(tài)局部變量
靜態(tài)局部變量屬于靜態(tài)存儲(chǔ)方式,它具有以下特點(diǎn):
(1)靜態(tài)局部變量在函數(shù)內(nèi)定義 它的生存期為整個(gè)源程序,但是其作用域仍與自動(dòng)變量相同,只能在定義該變量的函數(shù)內(nèi)使用該變量。退出該函數(shù)后, 盡管該變量還繼續(xù)存在,但不能使用它。
(2)允許對(duì)構(gòu)造類靜態(tài)局部量賦初值 例如數(shù)組,若未賦以初值,則由系統(tǒng)自動(dòng)賦以0值。
(3) 對(duì)基本類型的靜態(tài)局部變量若在說(shuō)明時(shí)未賦以初值,則系統(tǒng)自動(dòng)賦予0值。而對(duì)自動(dòng)變量不賦初值,則其值是不定的。
根據(jù)靜態(tài)局部變量的特點(diǎn),可以看出它是一種生存期為整個(gè)源程序的量。雖然離開(kāi)定義它的函數(shù)后不能使用,但如果再次調(diào)用定義它的函數(shù)時(shí),它又可繼續(xù)使用, 而且保存了前次被調(diào)用后留下的值。因此,當(dāng)多次調(diào)用一個(gè)函數(shù)且要求在調(diào)用之間保留某些變量的值時(shí),可考慮采用靜態(tài)局部變量。雖然用全局變量也可以達(dá)到上述目的,但全局變量有時(shí)會(huì)造成意外的副作用,因此仍以采用局部靜態(tài)變量為宜。
3.靜態(tài)全局變量
全局變量(外部變量)的說(shuō)明之前再冠以static 就構(gòu)成了靜態(tài)的全局變量。全局變量本身就是靜態(tài)存儲(chǔ)方式, 靜態(tài)全局變量當(dāng)然也是靜態(tài)存儲(chǔ)方式。這兩者在存儲(chǔ)方式上并無(wú)不同。這兩者的區(qū)別雖在于非靜態(tài)全局變量的作用域是整個(gè)源程序,當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),非靜態(tài)的全局變量在各個(gè)源文件中都是有效的。 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內(nèi)有效, 在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域局限于一個(gè)源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,因此 可以避免在其它源文件中引起錯(cuò)誤。
從以上分析可以看出:
把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲(chǔ)方式即改變了它的生存期
把全局變量改變?yōu)殪o態(tài)變量 后是改變了它的作用域,限制了它的使用范圍
因此static 這個(gè)說(shuō)明符在不同的地方所起的作用是不同的。
4. static 函數(shù)…..
內(nèi)部函數(shù)和外部函數(shù)
當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),C語(yǔ)言根據(jù)函數(shù)能否被其它源文件中的函數(shù)調(diào)用,將函數(shù)分為內(nèi)部函數(shù)和外部函數(shù)。
1 內(nèi)部函數(shù)(又稱靜態(tài)函數(shù))
如果在一個(gè)源文件中定義的函數(shù),只能被本文件中的函數(shù)調(diào)用,而不能被同一程序其它文件中的函數(shù)調(diào)用,這種函數(shù)稱為內(nèi)部函數(shù)。
定義一個(gè)內(nèi)部函數(shù),只需在函數(shù)類型前再加一個(gè)“static”關(guān)鍵字即可,如下所示:
static 函數(shù)類型 函數(shù)名(函數(shù)參數(shù)表)
{……}
關(guān)鍵字“static”,譯成中文就是“靜態(tài)的”,所以內(nèi)部函數(shù)又稱靜態(tài)函數(shù)。但此處“static”的含義不是指存儲(chǔ)方式,而是指對(duì)函數(shù)的作用域僅局限于本文件。
使用內(nèi)部函數(shù)的好處是:不同的人編寫(xiě)不同的函數(shù)時(shí),不用擔(dān)心自己定義的函數(shù),是否會(huì)與其它文件中的函數(shù)同名,因?yàn)橥矝](méi)有關(guān)系。
2 外部函數(shù)
外部函數(shù)的定義:在定義函數(shù)時(shí),如果沒(méi)有加關(guān)鍵字“static”,或冠以關(guān)鍵字“extern”,表示此函數(shù)是外部函數(shù):
[extern] 函數(shù)類型 函數(shù)名(函數(shù)參數(shù)表)
{……}
調(diào)用外部函數(shù)時(shí),需要對(duì)其進(jìn)行說(shuō)明:
[extern] 函數(shù)類型 函數(shù)名(參數(shù)類型表)[,函數(shù)名2(參數(shù)類型表2)……];
[案例]外部函數(shù)應(yīng)用。
(1)文件mainf.c
main()
{ extern void input(…),process(…),output(…); /*調(diào)用外部函數(shù)*/
input(…); process(…); output(…);
}
(2)文件subf1.c
……
extern void input(……) /*定義外部函數(shù)*/
{……}
(3)文件subf2.c
……
extern void process(……) /*定義外部 函數(shù)*/
{……}
(4)文件subf3.c
……
extern void output(……) /*定義外部函數(shù)*/
{……}
注:此處的extern可有可無(wú),不加extern時(shí)默認(rèn)是外部函數(shù)
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
1、概述static 聲明的變量在C語(yǔ)言中有兩方面的特征:1)、變量會(huì)被放在程序的全局存儲(chǔ)區(qū)中,這樣可以在下一次調(diào)用的時(shí)候還可以保持原來(lái)的賦值。這一點(diǎn)是它與堆棧變量和堆變量的區(qū)別。
2)、變量用static告知編譯器,自己僅僅在變量的作用范圍內(nèi)可見(jiàn)。這一點(diǎn)是它與全局變量的區(qū)別。
2、問(wèn)題:Static的理解 關(guān)于static變量,請(qǐng)選擇下面所有說(shuō)法正確的內(nèi)容:
A、若全局變量?jī)H在單個(gè)C文件中訪問(wèn),則可以將這個(gè)變量修改為靜態(tài)全局變量,以降低模塊間的耦合度;
B、若全局變量?jī)H由單個(gè)函數(shù)訪問(wèn),則可以將這個(gè)變量改為該函數(shù)的靜態(tài)局部變量,以降低模塊間的耦合度;
C、設(shè)計(jì)和使用訪問(wèn)動(dòng)態(tài)全局變量、靜態(tài)全局變量、靜態(tài)局部變量的函數(shù)時(shí),需要考慮重入問(wèn)題;
D、靜態(tài)全局變量過(guò)大,可那會(huì)導(dǎo)致堆棧溢出。
答案與分析:
對(duì)于A,B:根據(jù)本篇概述部分的說(shuō)明b),我們知道,A,B都是正確的。
對(duì)于C:根據(jù)本篇概述部分的說(shuō)明a),我們知道,C是正確的(所謂的函數(shù)重入問(wèn)題,下面會(huì)詳細(xì)闡述)。
對(duì)于D:靜態(tài)變量放在程序的全局?jǐn)?shù)據(jù)區(qū),而不是在堆棧中分配,所以不可能導(dǎo)致堆棧溢出,D是錯(cuò)誤的。
因此,答案是A、B、C。
3、問(wèn)題:不可重入函數(shù)
曾經(jīng)設(shè)計(jì)過(guò)如下一個(gè)函數(shù),在代碼檢視的時(shí)候被提醒有bug,因?yàn)檫@個(gè)函數(shù)是不可重入的,為什么?
unsigned int sum_int( unsigned int base ) { unsigned int index; static unsigned int sum = 0; // 注意,是static類型的。 for (index = 1; index <= base; index++) { sum += index; } return sum; } |
答案與分析:
所謂的函數(shù)是可重入的(也可以說(shuō)是可預(yù)測(cè)的),即:只要輸入數(shù)據(jù)相同就應(yīng)產(chǎn)生相同的輸出。
這個(gè)函數(shù)之所以是不可預(yù)測(cè)的,就是因?yàn)楹瘮?shù)中使用了static變量,因?yàn)閟tatic變量的特征,這樣的函數(shù)被稱為:帶“內(nèi)部存儲(chǔ)器”功能的的函數(shù)。
因此如果我們需要一個(gè)可重入的函數(shù),那么,我們一定要避免函數(shù)中使用static變量,這種函數(shù)中的static變量,使用原則是,能不用盡量不用。
將上面的函數(shù)修改為可重入的函數(shù)很簡(jiǎn)單,只要將聲明sum變量中的static關(guān)鍵字去掉,變量sum即變?yōu)橐粋(gè)auto 類型的變量,函數(shù)即變?yōu)橐粋(gè)可重入的函數(shù)。
當(dāng)然,有些時(shí)候,在函數(shù)中是必須要使用static變量的,比如當(dāng)某函數(shù)的返回值為指針類型時(shí),則必須是static的局部變量的地址作為返回值,若為auto類型,則返回為錯(cuò)指針。