嵌入式學習筆(bi)記:c語(yu)言static的作用
時間(jian):2018-09-21 來源:未知
伴隨著不(bu)同(tong)源文(wen)件變量(liang)和函(han)數之間的(de)相互引用(yong)以及相互獨立的(de)關系(xi),產(chan)生了extern和static關鍵字。
static關鍵字在編寫程序時有的三大類用(yong)法:
一,static全局(ju)變(bian)量

一個進程在內(nei)存中(zhong)的布局(ju)圖(tu)
其中.text段(duan)保(bao)(bao)存進(jin)程(cheng)(cheng)(cheng)所(suo)執行的程(cheng)(cheng)(cheng)序二進(jin)制(zhi)文件,.data段(duan)保(bao)(bao)存進(jin)程(cheng)(cheng)(cheng)所(suo)有(you)的已初(chu)始(shi)化(hua)的全局(ju)變(bian)(bian)量(liang),.bss段(duan)保(bao)(bao)存進(jin)程(cheng)(cheng)(cheng)未初(chu)始(shi)化(hua)的全局(ju)變(bian)(bian)量(liang)(其他段(duan)中還(huan)有(you)很多(duo)亂七八糟的段(duan),暫且不表)。在進(jin)程(cheng)(cheng)(cheng)的整(zheng)個(ge)生命(ming)周期中,.data段(duan)和.bss段(duan)內的數(shu)據時跟整(zheng)個(ge)進(jin)程(cheng)(cheng)(cheng)同生共死的,也就是在進(jin)程(cheng)(cheng)(cheng)結束之(zhi)后(hou)這些數(shu)據才會壽終就寢。
當一(yi)個進程(cheng)的(de)全(quan)(quan)局變(bian)量(liang)(liang)被(bei)聲明為static之后,它(ta)的(de)中文名叫靜態(tai)全(quan)(quan)局變(bian)量(liang)(liang)。靜態(tai)全(quan)(quan)局變(bian)量(liang)(liang)和其(qi)他的(de)全(quan)(quan)局變(bian)量(liang)(liang)的(de)存儲地(di)點并沒有區別(bie),都是在(zai).data段(已初始化)或
者(zhe).bss段(未初始(shi)化)內(nei),但是它(ta)(ta)只在(zai)定義它(ta)(ta)的(de)源(yuan)(yuan)文件(jian)內(nei)有效,其他源(yuan)(yuan)文件(jian)無法訪(fang)問它(ta)(ta)。所以,普(pu)通全局(ju)變(bian)量(liang)穿上static外衣后,它(ta)(ta)就變(bian)成(cheng)了新娘,已心有所屬,只能被定義它(ta)(ta)的(de)源(yuan)(yuan)文件(jian)(新郎)中的(de)變(bian)量(liang)或函數訪(fang)問
靜態全局變量有以下特點(dian):
該(gai)變量在(zai)全局數據(ju)區分配內存;
未(wei)經初始化(hua)的靜態全局(ju)變量會被(bei)(bei)程(cheng)序自動初始化(hua)為0(自動變量的值是隨機的,除非(fei)它(ta)被(bei)(bei)顯式初始化(hua));
靜(jing)態全局(ju)變量在聲明它的(de)整個文件(jian)都是可(ke)見的(de),而在文件(jian)之外是不可(ke)見的(de);靜(jing)態全局(ju)變量不能(neng)被其它文件(jian)所用;
其它文件中可以定義相同名字的變量,不會發(fa)生沖(chong)突;
靜(jing)態(tai)變量(liang)(liang)都在全(quan)局(ju)數據區分配內存,包括后面(mian)將要提到的靜(jing)態(tai)局(ju)部變量(liang)(liang)。對于一個完(wan)整的程序,在內存中(zhong)的分布情況如下(xia)圖:

代碼區
全局數據區
堆區
棧區
一般程(cheng)序(xu)的(de)(de)(de)由new產生的(de)(de)(de)動態(tai)數(shu)據(ju)存放(fang)(fang)在堆區(qu),函數(shu)內(nei)部(bu)的(de)(de)(de)自動變(bian)量(liang)存放(fang)(fang)在棧區(qu)。自動變(bian)量(liang)一般會隨著函數(shu)的(de)(de)(de)退出(chu)而釋放(fang)(fang)空(kong)(kong)間(jian),靜(jing)態(tai)數(shu)據(ju)(即使是函數(shu)內(nei)部(bu)的(de)(de)(de)靜(jing)態(tai)局部(bu)變(bian)量(liang))也存放(fang)(fang)在全局數(shu)據(ju)區(qu)。全局數(shu)據(ju)區(qu)的(de)(de)(de)數(shu)據(ju)并不會因為函數(shu)的(de)(de)(de)退出(chu)而釋放(fang)(fang)空(kong)(kong)間(jian)。
二,static局部變量
通常,在(zai)函(han)數體內定(ding)義了一個(ge)變量,每當程序運行到該語句時都(dou)會(hui)(hui)給該局部(bu)變量分配棧內存。但隨著程序退出(chu)函(han)數體,系統(tong)就會(hui)(hui)收回(hui)棧內存,局部(bu)變量也相應失效(xiao)。
普通的(de)局部(bu)變(bian)量(liang)在棧(zhan)空(kong)間上(shang)分配,這個局部(bu)變(bian)量(liang)所在的(de)函(han)數被多(duo)次(ci)調用時(shi),每次(ci)調用這個局部(bu)變(bian)量(liang)在棧(zhan)上(shang)的(de)位置都(dou)不一定相同(tong)。局部(bu)變(bian)量(liang)也(ye)可以在堆上(shang)動態(tai)分配,但是記得使用完這個堆空(kong)間后要釋放(fang)之。
有時候我(wo)們需(xu)要在兩次(ci)調用(yong)之間(jian)對變量的(de)值(zhi)進(jin)行(xing)保存。通常的(de)想法是定義一(yi)個全局變量來(lai)實現。但這樣一(yi)來(lai),變量已經不再屬于函(han)數(shu)本身了,不再僅受(shou)函(han)數(shu)的(de)控制,給(gei)程序的(de)維護帶來(lai)不便。
靜態局部變量(liang)正好可以解決(jue)這個問題。靜態局部變量(liang)保存(cun)在全局數(shu)據區,而(er)不是保存(cun)
在棧中(zhong),每次的值保持到下一(yi)次調(diao)用,直到下次賦新值
static局(ju)部變(bian)量(liang)(liang)中文名(ming)叫靜態局(ju)部變(bian)量(liang)(liang)。它與普通的(de)局(ju)部變(bian)量(liang)(liang)比起來有(you)如(ru)下幾個區別:
1)位置:靜態局(ju)部(bu)變量被(bei)編(bian)譯器放在(zai)全局(ju)存(cun)儲區.data(注(zhu)意(yi):不在(zai).bss段內,原因見3)),所(suo)以它雖然(ran)是局(ju)部(bu)的(de),但是在(zai)程(cheng)序的(de)整個生命(ming)周期(qi)中存(cun)在(zai)。
2)訪(fang)問(wen)權限:靜態局部變量(liang)只能(neng)被其作用域內(nei)的(de)(de)變量(liang)或函(han)數訪(fang)問(wen)。也(ye)就是說雖(sui)然它(ta)會在程序的(de)(de)整個生命周期(qi)中存在,由于它(ta)是static的(de)(de),它(ta)不能(neng)被其他的(de)(de)函(han)數和源文(wen)件訪(fang)
問。
3)值:靜(jing)態局部(bu)變(bian)量(liang)(liang)如果(guo)沒有被(bei)用(yong)戶初始化,則(ze)會被(bei)編譯(yi)器自動賦值為0,以后(hou)每(mei)次(ci)調(diao)用(yong)靜(jing)態局部(bu)變(bian)量(liang)(liang)的(de)時(shi)候(hou)都用(yong)上次(ci)調(diao)用(yong)后(hou)的(de)值。這個比較好理解,每(mei)次(ci)函(han)數調(diao)用(yong)靜(jing)態局部(bu)變(bian)量(liang)(liang)的(de)時(shi)候(hou)都修改它然后(hou)離開,下次(ci)讀的(de)時(shi)候(hou)從全(quan)局存儲區讀出的(de)靜(jing)態局部(bu)變(bian)量(liang)(liang)就是(shi)上次(ci)修改后(hou)的(de)值。
函數每次(ci)被(bei)調用,普通局(ju)部變量都是重(zhong)新分配,而靜態局(ju)部變量保持(chi)上(shang)次(ci)調用的值不(bu)變。
靜態局部變量(liang)有(you)以下特點:
(1)該(gai)變量在全局數據區分(fen)配內(nei)存;
(2)靜態局部(bu)變量在(zai)程序執行(xing)到該對象的聲(sheng)明處(chu)時被首(shou)次初始化,即以后的函(han)數調用不再進行(xing)初始化;
(3)靜態局部變(bian)量(liang)一(yi)般在聲明處初始(shi)化(hua),如果沒有顯(xian)式初始(shi)化(hua),會被程序自動(dong)初
始化為0;
(4)它(ta)始終(zhong)駐留在全局數(shu)據區(qu),直(zhi)到程序運(yun)行(xing)結束。但其(qi)作用(yong)域為(wei)局部(bu)作用(yong)域,當定(ding)義(yi)它(ta)的函數(shu)或語(yu)句塊結束時,其(qi)作用(yong)域隨之結束;
需要注意(yi)的(de)(de)是由于static局部(bu)變量的(de)(de)這種(zhong)特性(xing),使得(de)含靜態局部(bu)變量的(de)(de)函(han)數變得(de)不(bu)可(ke)重入,即(ji)每(mei)次(ci)調用可(ke)能(neng)會(hui)產生不(bu)同(tong)的(de)(de)結(jie)果。這在多線程編程時可(ke)能(neng)會(hui)成為一(yi)種(zhong)隱患。需要多
加注意。
三,static函數
相信大(da)家還記得C++面向對象編(bian)程(cheng)中(zhong)的(de)private函數(shu),私有(you)(you)函數(shu)只(zhi)有(you)(you)該類的(de)成員變量(liang)或成員函數(shu)可(ke)以訪問(wen)。在(zai)C語言中(zhong),也(ye)有(you)(you)“private函數(shu)”,它就是接下來要說的(de)static函數(shu),完成面向對象編(bian)程(cheng)中(zhong)private函數(shu)的(de)功能(neng)。
當(dang)你的(de)程序(xu)中有很多個(ge)源(yuan)文件的(de)時(shi)候(hou),你肯定會讓(rang)某個(ge)源(yuan)文件只提供一些(xie)(xie)(xie)外(wai)(wai)界需(xu)要的(de)接(jie)口,其(qi)他的(de)函數(shu)(shu)可能是為了實現(xian)這些(xie)(xie)(xie)接(jie)口而編寫,這些(xie)(xie)(xie)其(qi)他的(de)函數(shu)(shu)你可能并不希(xi)望被外(wai)(wai)界(非(fei)本源(yuan)文件)所(suo)看到,這時(shi)候(hou)就可以(yi)用(yong)static修飾這些(xie)(xie)(xie)“其(qi)他的(de)函數(shu)(shu)”。
所以static函數的作(zuo)用域是本源文件,把它想象為面向對象中(zhong)的private函數就(jiu)可(ke)以
了。
static函(han)數(shu)可以很(hen)好(hao)地解決不(bu)同原文件(jian)中函(han)數(shu)同名的(de)問題,因為(wei)一個源(yuan)文件(jian)對于(yu)其他(ta)源(yuan)文件(jian)中的(de)static函(han)數(shu)是不(bu)可見的(de)。
定義靜態函數的好(hao)處(chu):
靜態函數不能被其它文件所(suo)用;
其(qi)它文件中(zhong)可以定義相同(tong)名字的函數,不(bu)會發生沖突(tu);
面向對象的(de)static關鍵字
一、靜態數(shu)據成員
在類內數(shu)(shu)據(ju)成(cheng)員的聲明前加(jia)上關(guan)鍵字static,該(gai)數(shu)(shu)據(ju)成(cheng)員就是類內的靜態數(shu)(shu)據(ju)成(cheng)員。
靜態數據成員有以下特點:
對于非靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員,每(mei)個(ge)(ge)類(lei)對象(xiang)(xiang)都有(you)自己的(de)(de)拷貝。而靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員被當(dang)作是(shi)(shi)(shi)類(lei)的(de)(de)成(cheng)員。無論這個(ge)(ge)類(lei)的(de)(de)對象(xiang)(xiang)被定(ding)義了多少個(ge)(ge),靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員在(zai)程序中也只(zhi)有(you)一(yi)份(fen)拷貝,由該類(lei)型的(de)(de)所有(you)對象(xiang)(xiang)共(gong)享訪問。也就是(shi)(shi)(shi)說(shuo),靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員是(shi)(shi)(shi)該類(lei)的(de)(de)所有(you)對象(xiang)(xiang)所共(gong)有(you)的(de)(de)。對該類(lei)的(de)(de)多個(ge)(ge)對象(xiang)(xiang)來說(shuo),靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員只(zhi)分配一(yi)次(ci)內存,供所有(you)對象(xiang)(xiang)共(gong)用。所以(yi),靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員的(de)(de)值(zhi)對每(mei)個(ge)(ge)對象(xiang)(xiang)都是(shi)(shi)(shi)一(yi)樣的(de)(de),它的(de)(de)值(zhi)可以(yi)更新;靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員存儲在(zai)全(quan)局(ju)數(shu)(shu)(shu)(shu)據(ju)(ju)區。靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員定(ding)義時要分配空間(jian),所以(yi)不能在(zai)類(lei)聲明中定(ding)義。在(zai)Example 5中,語句(ju)int Myclass::Sum=0;是(shi)(shi)(shi)定(ding)義靜(jing)(jing)(jing)態(tai)(tai)數(shu)(shu)(shu)(shu)據(ju)(ju)成(cheng)員;
靜態數據成(cheng)員和普通數據成(cheng)員一樣遵從public,protected,private訪問規則;
因為(wei)靜態(tai)數據(ju)成(cheng)(cheng)員在全局數據(ju)區(qu)分配(pei)內(nei)存,屬(shu)于(yu)本類(lei)的(de)所(suo)有對(dui)象共享(xiang),所(suo)以,它不屬(shu)于(yu)特定的(de)類(lei)對(dui)象,在沒(mei)(mei)有產(chan)(chan)生類(lei)對(dui)象時其(qi)作用域就(jiu)可見,即在沒(mei)(mei)有產(chan)(chan)生類(lei)的(de)實例時,我們就(jiu)可以操作它;靜態(tai)數據(ju)成(cheng)(cheng)員初(chu)始化(hua)(hua)與(yu)一(yi)般數據(ju)成(cheng)(cheng)員初(chu)始化(hua)(hua)不同(tong)。靜態(tai)數據(ju)成(cheng)(cheng)員初(chu)始化(hua)(hua)的(de)格式(shi)為(wei):
<數據類(lei)型><類(lei)名(ming)>::<靜(jing)態數據成員名(ming)>=<值(zhi)>
類的(de)靜態數據(ju)成員有兩種(zhong)訪問形式(shi):
<類(lei)對(dui)象名(ming)>.<靜(jing)(jing)態(tai)(tai)數據(ju)成員(yuan)名(ming)> 或 <類(lei)類(lei)型名(ming)>::<靜(jing)(jing)態(tai)(tai)數據(ju)成員(yuan)名(ming)>如果靜(jing)(jing)態(tai)(tai)數據(ju)成員(yuan)的訪問(wen)權限(xian)允(yun)許的話(即public的成員(yuan)),可在(zai)程序中,按上(shang)
述格式來引用(yong)靜態數據成員 ;
靜態數據成(cheng)員(yuan)主(zhu)要(yao)用在(zai)各個(ge)(ge)對象都有相同(tong)的(de)(de)(de)某項屬性的(de)(de)(de)時候。比如對于一(yi)個(ge)(ge)存款(kuan)類(lei),每個(ge)(ge)實例的(de)(de)(de)利(li)息(xi)都是(shi)相同(tong)的(de)(de)(de)。所(suo)以,應該(gai)把利(li)息(xi)設為(wei)存款(kuan)類(lei)的(de)(de)(de)靜態數據成(cheng)員(yuan)。這有兩(liang)個(ge)(ge)好處(chu),第一(yi),不管定義多少個(ge)(ge)存款(kuan)類(lei)對象,利(li)息(xi)數據成(cheng)員(yuan)都共(gong)享分(fen)配在(zai)全局數據區的(de)(de)(de)內存,所(suo)以節(jie)省存儲空(kong)間。第二,一(yi)旦利(li)息(xi)需要(yao)改(gai)(gai)變時,只(zhi)要(yao)改(gai)(gai)變一(yi)次,則所(suo)有存款(kuan)類(lei)對象的(de)(de)(de)利(li)息(xi)全改(gai)(gai)變過來(lai)了;
同全局變量相比,使用(yong)靜態數據成員有兩個優勢:
1、靜(jing)態(tai)數據成(cheng)員(yuan)沒有進入程序的全局名字空間,因此不存(cun)在與程序中其(qi)它全局名字沖(chong)突的可(ke)能(neng)性;
2、可(ke)以(yi)實現信息(xi)隱藏。靜態數據成員可(ke)以(yi)是private成員,而全局變量(liang)不能;
二(er)、靜態成(cheng)員函數
與靜態(tai)(tai)數(shu)(shu)(shu)據成(cheng)員(yuan)一樣,我們也(ye)可以創建一個靜態(tai)(tai)成(cheng)員(yuan)函數(shu)(shu)(shu),它為(wei)類(lei)的(de)(de)(de)(de)(de)全(quan)部服務而不是(shi)(shi)(shi)為(wei)某一個類(lei)的(de)(de)(de)(de)(de)具(ju)體對象(xiang)服務。靜態(tai)(tai)成(cheng)員(yuan)函數(shu)(shu)(shu)與靜態(tai)(tai)數(shu)(shu)(shu)據成(cheng)員(yuan)一樣,都(dou)(dou)是(shi)(shi)(shi)類(lei)的(de)(de)(de)(de)(de)內部實(shi)現,屬(shu)(shu)于類(lei)定義的(de)(de)(de)(de)(de)一部分。普(pu)通(tong)的(de)(de)(de)(de)(de)成(cheng)員(yuan)函數(shu)(shu)(shu)一般都(dou)(dou)隱含了一個this指針,this指針指向類(lei)的(de)(de)(de)(de)(de)對象(xiang)本身,因為(wei)普(pu)通(tong)成(cheng)員(yuan)函數(shu)(shu)(shu)總是(shi)(shi)(shi)具(ju)體的(de)(de)(de)(de)(de)屬(shu)(shu)于某個類(lei)的(de)(de)(de)(de)(de)具(ju)體對象(xiang)的(de)(de)(de)(de)(de)。通(tong)常情況下,this是(shi)(shi)(shi)缺省(sheng)的(de)(de)(de)(de)(de)。如函數(shu)(shu)(shu)fn()實(shi)際上是(shi)(shi)(shi)this->fn()。但是(shi)(shi)(shi)與普(pu)通(tong)函數(shu)(shu)(shu)相比(bi),靜態(tai)(tai)成(cheng)員(yuan)函數(shu)(shu)(shu)由(you)于不是(shi)(shi)(shi)與任何(he)的(de)(de)(de)(de)(de)對象(xiang)相聯系,因此(ci)它不具(ju)有(you)this指針。從這個意義上講,它無法(fa)訪問(wen)屬(shu)(shu)于類(lei)對象(xiang)的(de)(de)(de)(de)(de)非靜態(tai)(tai)數(shu)(shu)(shu)據成(cheng)員(yuan),也(ye)無法(fa)訪問(wen)非靜態(tai)(tai)成(cheng)員(yuan)函數(shu)(shu)(shu),它只能調用(yong)其(qi)余(yu)的(de)(de)(de)(de)(de)靜態(tai)(tai)成(cheng)員(yuan)函數(shu)(shu)(shu)。

關于(yu)靜態成(cheng)員函(han)數(shu),可(ke)以(yi)總結為以(yi)下幾點:
出現在類體外的函(han)數定義不能指定關鍵字static;
靜態(tai)成(cheng)(cheng)員之間(jian)可以(yi)相互訪問,包括靜態(tai)成(cheng)(cheng)員函數訪問靜態(tai)數據成(cheng)(cheng)員和訪問靜態(tai)成(cheng)(cheng)員函數;
非(fei)靜(jing)態成員(yuan)(yuan)函(han)(han)數(shu)(shu)可以任意地訪問靜(jing)態成員(yuan)(yuan)函(han)(han)數(shu)(shu)和(he)靜(jing)態數(shu)(shu)據成員(yuan)(yuan);靜(jing)態成員(yuan)(yuan)函(han)(han)數(shu)(shu)不能訪問非(fei)靜(jing)態成員(yuan)(yuan)函(han)(han)數(shu)(shu)和(he)非(fei)靜(jing)態數(shu)(shu)據成員(yuan)(yuan);
由于(yu)沒有this指針(zhen)的(de)額外開(kai)銷,因(yin)此靜(jing)態(tai)成員函(han)數(shu)與類(lei)的(de)全(quan)局函(han)數(shu)相比速度上會(hui)有少(shao)許的(de)增(zeng)長;調(diao)用靜(jing)態(tai)成員函(han)數(shu),可(ke)以用成員訪問(wen)操作符(.)和(he)(->)為一個類(lei)的(de)對象(xiang)(xiang)或指向類(lei)對象(xiang)(xiang)的(de)指針(zhen)調(diao)用靜(jing)態(tai)成員函(han)數(shu),也可(ke)以直(zhi)接使用如下格式:
<類名(ming)>::<靜態成員函數名(ming)>(<參數表>)
調用類的靜(jing)態成員函數。

