- 編寫高質量代碼:改善C程序代碼的125個建議
- 馬偉 著
- 1663字
- 2019-01-01 01:33:14
建議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的運行結果
- Rust實戰
- Raspberry Pi for Secret Agents(Third Edition)
- VMware vSphere 6.7虛擬化架構實戰指南
- SQL語言從入門到精通
- Learn Swift by Building Applications
- Python數據分析(第2版)
- Kotlin Standard Library Cookbook
- PhpStorm Cookbook
- 從Excel到Python:用Python輕松處理Excel數據(第2版)
- 鴻蒙OS應用編程實戰
- 3ds Max印象 電視欄目包裝動畫與特效制作
- 監控的藝術:云原生時代的監控框架
- Mastering Android Studio 3
- 零基礎學Java第2版
- HTML5游戲開發實戰