C語言中的static 詳細(xì)分析

C語言代碼是以文件為單位來組織的毡代,在一個源程序的所有源文件中禁添,一個外部變量(注意不是局部變量)或者函數(shù)只能在一個源程序中定義一次黍判,如果有重復(fù)定義的話編譯器就會報錯。伴隨著不同源文件變量和函數(shù)之間的相互引用以及相互獨(dú)立的關(guān)系伪节,產(chǎn)生了extern和static關(guān)鍵字。
下面绩鸣,詳細(xì)分析一下static關(guān)鍵字在編寫程序時有的三大類用法:

一怀大,static全局變量
我們知道,一個進(jìn)程在內(nèi)存中的布局如圖1所示:


其中.text段保存進(jìn)程所執(zhí)行的程序二進(jìn)制文件呀闻,.data段保存進(jìn)程所有的已初始化的全局變量化借,.bss段保存進(jìn)程未初始化的全局變量(其他段中還有很多亂七八糟的段,暫且不表)捡多。在進(jìn)程的整個生命周期中蓖康,.data段和.bss段內(nèi)的數(shù)據(jù)時跟整個進(jìn)程同生共死的,也就是在進(jìn)程結(jié)束之后這些數(shù)據(jù)才會壽終就寢垒手。
當(dāng)一個進(jìn)程的全局變量被聲明為static之后蒜焊,它的中文名叫靜態(tài)全局變量。靜態(tài)全局變量和其他的全局變量的存儲地點(diǎn)并沒有區(qū)別科贬,都是在.data段(已初始化)或者.bss段(未初始化)內(nèi)山涡,但是它只在定義它的源文件內(nèi)有效,其他源文件無法訪問它唆迁。所以鸭丛,普通全局變量穿上static外衣后,它就變成了新娘唐责,已心有所屬鳞溉,只能被定義它的源文件(新郎)中的變量或函數(shù)訪問。
以下是一些示例程序
file1.h如下:
#include <stdio.h>

void printStr();  

我們在file1.c中定義一個靜態(tài)全局變量hello, 供file1.c中的函數(shù)printStr訪問.

#include "file1.h"  

static char* hello = "hello cobing!";  

void printStr()  
{  
    printf("%s\n", hello);  
}  

file2.c是我們的主程序所在文件鼠哥,file2.c中如果引用hello會編譯出錯
#include "file1.h"

int main()  
{  
    printStr();  
    printf("%s\n", hello);  
    return 0;  
}  

報錯如下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2file2.c: In function ‘main’:file2.c:6: 錯誤:‘hello’ 未聲明 (在此函數(shù)內(nèi)第一次使用)file2.c:6: 錯誤:(即使在一個函數(shù)內(nèi)多次出現(xiàn)熟菲,每個未聲明的標(biāo)識符在其file2.c:6: 錯誤:所在的函數(shù)內(nèi)只報告一次看政。)如果我們將file2.c改為下面的形式:

#include "file1.h"  

int main()  
{  
    printStr();  
    return 0;  
}  

則會順利編譯連接。
運(yùn)行程序后的結(jié)果如下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2[liujx@server235 static]$ ./file2hello cobing!上面的例子中抄罕,file1.c中的hello就是一個靜態(tài)全局變量允蚣,它可以被同一文件中的printStr調(diào)用,但是不能被不同源文件中的file2.c調(diào)

二呆贿,static局部變量
普通的局部變量在椚峦茫空間上分配,這個局部變量所在的函數(shù)被多次調(diào)用時做入,每次調(diào)用這個局部變量在棧上的位置都不一定相同冒晰。局部變量也可以在堆上動態(tài)分配,但是記得使用完這個堆空間后要釋放之竟块。
static局部變量中文名叫靜態(tài)局部變量壶运。它與普通的局部變量比起來有如下幾個區(qū)別:
1)位置:靜態(tài)局部變量被編譯器放在全局存儲區(qū).data(注意:不在.bss段內(nèi),原因見3))浪秘,所以它雖然是局部的蒋情,但是在程序的整個生命周期中存在。
2)訪問權(quán)限:靜態(tài)局部變量只能被其作用域內(nèi)的變量或函數(shù)訪問耸携。也就是說雖然它會在程序的整個生命周期中存在恕出,由于它是static的,它不能被其他的函數(shù)和源文件訪問违帆。
3)值:靜態(tài)局部變量如果沒有被用戶初始化浙巫,則會被編譯器自動賦值為0,以后每次調(diào)用靜態(tài)局部變量的時候都用上次調(diào)用后的值刷后。這個比較好理解的畴,每次函數(shù)調(diào)用靜態(tài)局部變量的時候都修改它然后離開,下次讀的時候從全局存儲區(qū)讀出的靜態(tài)局部變量就是上次修改后的值尝胆。以下是一些示例程序:
file1.h的內(nèi)容和上例中的相同丧裁,file1.c的內(nèi)容如下:
#include "file1.h"

void printStr()  
{  
    int normal = 0;  
    static int stat = 0;    //this is a static local var  
    printf("normal = %d ---- stat = %d\n",normal, stat);  
    normal++;  
    stat++;  
}  

為了便于比較,我定義了兩個變量:普通局部變量normal和靜態(tài)局部變量stat含衔,它們都被賦予初值0煎娇;
file2.c中調(diào)用file1.h:

#include "file1.h"  

int main()  
{  
    printStr();  
    printStr();  
    printStr();  
    prin tStr();  
    printf("call stat in main: %d\n",stat);  
    return 0;  
}  

這個調(diào)用會報錯,因為file2.c中引用了file1.c中的靜態(tài)局部變量stat贪染,如下:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2file2.c: In function ‘main’:file2.c:9: 錯誤:‘stat’ 未聲明 (在此函數(shù)內(nèi)第一次使用)file2.c:9: 錯誤:(即使在一個函數(shù)內(nèi)多次出現(xiàn)缓呛,每個未聲明的標(biāo)識符在其file2.c:9: 錯誤:所在的函數(shù)內(nèi)只報告一次。)

編譯器說stat未聲明杭隙,這是因為它看不到file1.c中的stat哟绊,下面注掉這一行:

#include "file1.h"  

int main()  
{  
    printStr();  
    printStr();  
    printStr();  
    printStr();  
//  printf("call stat in main: %d\n",stat);  
    return 0;  
}  

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2[liujx@server235 static]$ ./file2normal = 0 ---- stat = 0normal = 0 ---- stat = 1normal = 0 ---- stat = 2normal = 0 ---- stat = 3運(yùn)行如上所示√翟鳎可以看出票髓,函數(shù)每次被調(diào)用攀涵,普通局部變量都是重新分配,而靜態(tài)局部變量保持上次調(diào)用的值不變洽沟。

需要注意的是由于static局部變量的這種特性以故,使得含靜態(tài)局部變量的函數(shù)變得不可重入,即每次調(diào)用可能會產(chǎn)生不同的結(jié)果裆操。這在多線程編程時可能會成為一種隱患怒详。需要多加注意。

三跷车,static函數(shù) 相信大家還記得C++面向?qū)ο缶幊讨械膒rivate函數(shù),私有函數(shù)只有該類的成員變量或成員函數(shù)可以訪問橱野。在C語言中朽缴,也有“private函數(shù)”,它就是接下來要說的static函數(shù)水援,完成面向?qū)ο缶幊讨衟rivate函數(shù)的功能密强。

當(dāng)你的程序中有很多個源文件的時候,你肯定會讓某個源文件只提供一些外界需要的接口蜗元,其他的函數(shù)可能是為了實(shí)現(xiàn)這些接口而編寫或渤,這些其他的函數(shù)你可能并不希望被外界(非本源文件)所看到,這時候就可以用static修飾這些“其他的函數(shù)”奕扣。

所以static函數(shù)的作用域是本源文件薪鹦,把它想象為面向?qū)ο笾械膒rivate函數(shù)就可以了。

下面是一些示例:
file1.h如下:
#include <stdio.h>

static int called();  
void printStr();  

file1.c如下:
#include "file1.h"

static int called()  
{  
    return 6;  
}  
void printStr()  
{  
    int returnVal;  
    returnVal = called();  
    printf("returnVal=%d\n",returnVal);  
}  

file2.c中調(diào)用file1.h中聲明的兩個函數(shù)惯豆,此處我們故意調(diào)用called():
#include "file1.h"  

int main()  
{  
    int val;  
    val = called();  
    printStr();  
    return 0;  
}  

編譯時會報錯:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2file1.h:3: 警告:‘called’ 使用過但從未定義/tmp/ccyLuBZU.o: In function `main':file2.c:(.text+0x12): undefined reference to `called'collect2: ld 返回 1因為引用了file1.h中的static函數(shù)池磁,所以file2.c中提示找不到這個函數(shù):undefined reference to 'called'

下面修改file2.c:

#include "file1.h"  

int main()  
{  
    printStr();  
    return 0;  
}  

編譯運(yùn)行:

[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2[liujx@server235 static]$ ./file2returnVal=6

static函數(shù)可以很好地解決不同原文件中函數(shù)同名的問題,因為一個源文件對于其他源文件中的static函數(shù)是不可見的楷兽。

原文:http://blog.csdn.net/keyeagle/article/details/6708077

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末地熄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子芯杀,更是在濱河造成了極大的恐慌端考,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揭厚,死亡現(xiàn)場離奇詭異却特,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)筛圆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門核偿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人顽染,你說我怎么就攤上這事漾岳『涿啵” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵尼荆,是天一觀的道長左腔。 經(jīng)常有香客問我,道長捅儒,這世上最難降的妖魔是什么液样? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮巧还,結(jié)果婚禮上鞭莽,老公的妹妹穿的比我還像新娘。我一直安慰自己麸祷,他們只是感情好澎怒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阶牍,像睡著了一般喷面。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上走孽,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天惧辈,我揣著相機(jī)與錄音,去河邊找鬼磕瓷。 笑死盒齿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的困食。 我是一名探鬼主播县昂,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陷舅!你這毒婦竟也來了倒彰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤莱睁,失蹤者是張志新(化名)和其女友劉穎待讳,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仰剿,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡创淡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了南吮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琳彩。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出露乏,到底是詐尸還是另有隱情碧浊,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布瘟仿,位于F島的核電站箱锐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏劳较。R本人自食惡果不足惜驹止,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望观蜗。 院中可真熱鬧臊恋,春花似錦、人聲如沸墓捻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毙替。三九已至岸售,卻和暖如春践樱,著一層夾襖步出監(jiān)牢的瞬間厂画,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工拷邢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袱院,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓瞭稼,卻偏偏與公主長得像忽洛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子环肘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

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

  • 引用自Cobing LiuC語言代碼是以文件為單位來組織的欲虚,在一個源程序的所有源文件中,一個外部變量(注意不是局部...
    mode1943閱讀 404評論 0 0
  • 1悔雹、c語言的函數(shù)有以下特點(diǎn): (1)才源程序由函數(shù)組成复哆,一個主函數(shù)main()+若干其他函數(shù) C程序中的函數(shù)類似文...
    滕王閣序閱讀 1,342評論 0 6
  • C++的static有兩種用法:面向過程程序設(shè)計中的static和面向?qū)ο蟪绦蛟O(shè)計中的static。前者應(yīng)用于普通...
    yangqi916閱讀 391評論 0 0
  • 裴佳源編輯 隨風(fēng)飄香的 菊花啊 菊園里的 菊樹上 有我昨天才放的 娃娃 今天我生病了 躺在床上 剛剛來過的 醫(yī)生 ...
    牛牛小哆閱讀 191評論 0 0
  • 走進(jìn)魯迅故里腌零,一條古色古香的樸素小巷由近至遠(yuǎn)梯找,河上的烏篷船,仿佛訴說著歷史益涧! 魯迅筆下的孔乙己锈锤,“多乎哉?不多也!...
    明明姐閱讀 1,124評論 1 7