官术网_书友最值得收藏!

建議8-3:不要混淆static變量的作用

在C語言中,static關鍵字不僅可以用來修飾變量,還可以用來修飾函數。在使用static關鍵字修飾變量時,我們稱此變量為靜態變量。靜態變量的存儲方式與全局變量一樣,都是靜態存儲方式。但這里需要特別說明的是,靜態變量屬于靜態存儲方式,屬于靜態存儲方式的變量卻不一定就是靜態變量。例如,全局變量雖然屬于靜態存儲方式,但并不是靜態變量,它必須由static加以定義后才能成為靜態全局變量。

考慮到可能會有不少讀者對靜態變量作用不太清楚,本節就來詳細討論一下它的主要作用。

1.隱藏與隔離的作用

上面已經闡述過,全局變量雖然屬于靜態存儲方式,但并不是靜態變量。全局變量的作用域是整個源程序,當一個源程序由多個源文件組成時,全局變量在各個源文件中都是有效的,比如上面代碼清單1-26-main中的全局變量g_X與g_Y就是如此。

如果我們希望全局變量僅限于在本源文件中使用,在其他源文件中不能引用,也就是說限制其作用域只在定義該變量的源文件內有效,而在同一源程序的其他源文件中不能使用。這時,就可以通過在全局變量之前加上關鍵字static來實現,即使全局變量被定義成為一個靜態全局變量。下面將代碼清單1-26-main中的全局變量g_X與g_Y全部修改為靜態全局變量,代碼如下所示:


#include <stdio.h>
/*定義兩個靜態全局變量*/
static int g_X=10;
static int g_Y=20;
int max();
int main(void)
{
    int result;
    result = max();
    printf("the max value is %d\n",result);
    return 0;
}

這時候,我們再來編譯該程序,代碼清單1-26-max將無法調用代碼清單1-26-main中的靜態全局變量g_X與g_Y。也就是說靜態全局變量g_X與g_Y只能在代碼清單1-26-main中使用,如圖1-41所示。

圖1-41 代碼清單1-26-main將g_X與g_Y定義為靜態全局變量的運行結果

在圖1-41中,雖然g_X與g_Y變量仍然是全局的,但由于靜態全局變量的作用域局限于一個源文件內,所以只能為該源文件內的函數所共用,這樣就可以避免在其他源文件中引起的錯誤。也就起到了對其他源文件進行隱藏與隔離錯誤的作用,有利于模塊化程序設計。

2.保持變量內容的持久性

有時候,我們希望函數中局部變量的值在函數調用結束之后不會消失,而仍然保留其原值。即它所占用的存儲單元不釋放,在下一次調用該函數時,其局部變量的值仍然存在,也就是上一次函數調用結束時的值。這時候,我們就應該將該局部變量用關鍵字static聲明為“靜態局部變量”。

當將局部變量聲明為靜態局部變量的時候,也就改變了局部變量的存儲位置,即從原來的棧中存放改為靜態存儲區存放。這讓它看起來很像全局變量,其實靜態局部變量與全局變量的主要區別就在于可見性,靜態局部變量只在其被聲明的代碼塊中是可見的。

對某些必須在調用之間保持局部變量的值的子程序而言,靜態局部變量是特別重要的。如果沒有靜態局部變量,則必須在這類函數中使用全局變量,由此也就打開了引入副作用的大門。使用靜態局部變量最好的示例就是實現統計次數的功能,如代碼清單1-27所示。

代碼清單1-27 靜態局部變量使用示例


#include <stdio.h>
void count();
int main(void)
{
    int i=0;
    for (i = 0; i <= 5; i++)
    {
            count();
    }
    return 0;
}
void count()
{
    /*聲明一個靜態局部變量*/
    static num = 0;
    num++;
    printf("%d\n",num);
}

在代碼清單1-27中,我們通過在count()函數里聲明一個靜態局部變量num來作為計數器。因為靜態局部變量是在編譯時賦初值的,且只賦初值一次,在程序運行時它已有初值。以后在每次調用函數時就不再重新賦初值,而是保留上次函數調用結束時的值。這樣,count()函數每次被調用的時候,靜態局部變量num就會保持上一次調用的值,然后再執行自增運算,這樣就實現了計數功能。同時,它又避免了使用全局變量。

通過上面的示例,我們可以得出靜態局部變量一般的使用場景,如下所示:

□ 需要保留函數上一次調用結束時的值。

□ 如果初始化后,變量只會被引用而不會改變其值,則這時用靜態局部變量比較方便,以免每次調用時重新賦值。

3.默認初始化為0

在靜態數據區,內存中所有的字節默認值都是0x00。靜態變量與全局變量也一樣,它們都存儲在靜態數據區中,因此其變量的值默認也為0。演示示例如代碼清單1-28所示。

代碼清單1-28 默認為0的演示示例


#include <stdio.h>
static int g_x;
int g_y;
int main(void)
{
    static int x;
    printf("g_x:%d\ng_y:%d\nx:%d",g_x,g_y,x);
    return 0;
}

代碼清單1-28的運行結果如圖1-42所示。

圖1-42 代碼清單1-28的運行結果

主站蜘蛛池模板: 温泉县| 梨树县| 台安县| 余姚市| 惠东县| 定兴县| 启东市| 瑞丽市| 龙岩市| 广南县| 安平县| 郑州市| 靖远县| 临清市| 南澳县| 日照市| 山阴县| 涞水县| 镇雄县| 乡城县| 崇阳县| 冷水江市| 平武县| 昆明市| 黎川县| 长沙市| 凤凰县| 阿合奇县| 河源市| 合江县| 临城县| 启东市| 施甸县| 怀来县| 夏津县| 梁河县| 青浦区| 英吉沙县| 周口市| 上高县| 鸡西市|