static在c裡面可以用來修飾變數,也可以用來修飾函數。
先看用來修飾變數的時候。變數在c裡面可分為存在全域資料區、棧和堆裡。其實我們平時所說的堆棧是棧而不是堆,不要弄混。
複製代碼 代碼如下:
int a ;
int main()
{
int b ;
int c* = (int *)malloc(sizeof(int));
}
a是全域變數,b是棧變數,c是堆變數。
static對全域變數的修飾,可以認為是限制了只能是本檔案引用此變數。有的程式是由好多.c檔案構成。彼此可以互相引用變數,但加入static修飾之後,只能被本檔案中函數引用此變數。
static對棧變數的修飾,可以認為棧變數的生命週期延長到程式執行結束時。一般來說,棧變數的生命週期由OS管理,在退棧的過程中,棧變數的生命也就結束了。但加入static修飾之後,變數已經不再儲存在棧中,而是和全域變數一起儲存。同時,離開定義它的函數後不能使用,但如再次調用定義它的函數時,它又可繼續使用, 而且儲存了前次被調用後留下的值。
static對函數的修飾與對全域變數的修飾相似,只能被本檔案中的函數調用,而不能被同一程式其它檔案中的函數調用。
檔案a.c
複製代碼 代碼如下:
static int i; //只在a檔案中用
int j; //在工程裡用
static void init() //只在a檔案中用
{
}
void callme() //在工程中用
{
static int sum;
}
上面的全域i變數和init()函數只能用在a.c檔案中,全域變數sum的範圍只在callme裡。變數j和函數callme()的全域限擴充到整個工程檔案。所以可以在下面的b.c中用extern關鍵字調用。extern告訴編譯器這個變數或者函數在其他檔案裡已經被定義了。
檔案b.c
複製代碼 代碼如下:
extern int j; //調用a檔案裡的
extern void callme(); //調用a檔案裡的
int main()
{
...
}
extern的另外用法是當C和C++混合編程時如果c++調用的是c源檔案定義的函數或者變數,那麼要加extern來告訴編譯器用c方式命名函數:
檔案A.cpp調用a.c裡面的變數i和函數callme()
複製代碼 代碼如下:
extern "C" //在c++檔案裡調用c檔案中的變數
{
int j;
void callme();
}
int main()
{
callme();
}
二 static法則:
A、若全域變數僅在單個C檔案中訪問,則可以將這個變數修改為靜態全域變數,以降低模組間的耦合度;
B、若全域變數僅由單個函數訪問,則可以將這個變數改為該函數的靜態局部變數,以降低模組間的耦合度;
C、設計和使用訪問動態全域變數、靜態全域變數、靜態局部變數的函數時,需要考慮重入問題;
全域變數有外部、靜態兩種儲存方式。
(1)全域變數一般用外部儲存方式儲存,用保留字extern加以定義。此時,變數的範圍是構成整個程式的所有程式檔案,也就是定義的外部變數可供其它程式檔案使用。
使用這樣的全域變數一定要非常謹慎,一旦產生錯誤,將波及整個程式。
(2)如果希望全域變數僅限於本程式檔案使用,而其它程式檔案中不能引用,這時必須將其儲存方式定義為靜態儲存方式,用保留字static加以定義。此時稱為靜態外部變數。
例如,在上例檔案filel.c中,如果作這樣的定義:
static int a:
則變數a的範圍被縮小至本程式檔案filel.c,檔案file2.c中不能引用。
值得注意的是對全域變數加static,定義為靜態儲存方式,並不意味著是靜態儲存;而不加static,是動態儲存裝置。兩種形式的全域變數(外部變數)都是靜態儲存方式,都是編譯時間分配儲存空間,但範圍不同。使用靜態外部變數,有利於隔離錯誤,有利於模組化程式設計。
(3)全域變數的預設儲存方式是外部儲存方式。
前面章節中的程式沒有見到變數的儲存類別定義,實際上採用變數的預設儲存方式。對局部變數採用auto方式,對全域變數採用extern方式。這也是至今為止,我們在程式中沒有見到auto、extern等的原因。
至此,我們對變數的儲存類別及資料類型進行了全面討論,在此作個小結。
1.變數定義的一般形式
儲存類別資料類型變數表;
2.變數定義的作用
①規定了變數的取值範圍。
②規定了變數進行的運行操作。
③規定了變數的範圍。
④規定了變數的儲存方式。
⑤規定了變數佔用的儲存空間。
3.局部變數和全域變數
從範圍角度將變數分為局部變數和全域變數。它們採取的儲存類別如下:
局部變數:
①自動變數,即動態局部變數(離開函數,值就消失)。
②靜態局部變數(離開函數,值仍保留)。
③寄存器變數(離開函數,值就消失)。
④形式參數可以定義為自動變數或寄存器變數。
全域變數:
①靜態外部變數(只限本程式檔案使用)。
②外部變數(即非靜態外部變數,允許其它程式檔案引用)。
4.動態儲存裝置和靜態儲存
從變數存在時間可將變數儲存分為動態儲存裝置和靜態儲存。靜態儲存是在整個程式運行時都存在,而動態儲存裝置則是在調用函數時臨時分配儲存單元。
動態儲存裝置:
①自動變數(函數內有效)。
②寄存器變數(函數內有效)。
③形式參數。
靜態儲存:
①靜態局部變數(函數內有效)。
②靜態外部變數(本程式檔案內有效)。
③外部變數(整個程式可引用)。
5.靜態儲存區和動態儲存裝置區
從變數值存放的位置可將變數儲存區分為靜態儲存區和動態儲存裝置區:
記憶體中靜態儲存區:
①靜態局部變數。
②靜態外部變數。
③外部變數(可被同一程式其它檔案引用)。
記憶體中動態儲存裝置區:自動變數和形式參數。
CPU中的寄存器:寄存器變數。