C語言中對變量的說明包括兩方面的內容:變量類型以及變量的存儲類型。變量類型如:int(整形),char(字符型)是用來說明變量所占用的內存空間的大小。變量存儲類型用來說明變量的作用范圍。
C語言的變量存儲類型有:自動類、寄存器類、靜態類和外部類。
局部變量是指在函數內部說明的變量(有時也稱為自動變量),用關鍵字auto進行說明。 所有的非全程變量都被認為是局部變量,所以auto實際上從來不用。局部變量在函數調用時自動產生,但不會自動初始化, 隨函數調用的結束,這個變量也就自動消失了,下次調用此函數時再自動產生,還要重新賦值,退出時又自動消失。
靜態變量用關鍵字static聲明。根據變量的類型可以分為靜態局部變量和靜態全程變量。
它與局部變量的區別在於:在函數退出時,這個變量始終存在,但不能被其它函數使用,當再次進入該函數時,將保存上次的結果。其它與局部變量一樣。
靜態全程變量就是指只在定義它的源文件中可見而在其它源文件中不可見的變量。它與全程變量的區別是:全程變量可以再說明為外部變量(extern),被其它源文件使用,而靜態全程變量卻不能再被說明為外部的,即只能被所在的源文件使用。
下面結合具體代碼來分析一下變量的種類。
在file1.c的開頭聲明i是全程變量,並初始化為1。而在main函數內部,說明了兩個自動變量i和j,這樣在main內部出現的i就是自動變量。
file1.c
#include <stdlib.h> #include <stdio.h> int reset(); int next(); int last(); int sum(int ); int i=1; void main() { auto int i,j; i=reset(); for(j=1;j<=3;j++) { printf("i=%dtj=%dn",i,j); printf("next(i)=%dn",next()); printf("last(i)=%dn",last()); printf("sum(i+j)=%dn",sum(i+j)); } }
file2.c文件一開始就定義了變量i,並聲明為靜態變量,因此它的使用范圍只在當前文件中使用。然而從函數sum中定義來看,其內部用到的i是形式參數,j是內部靜態變量,它們與以前的i, j都不同。
file2.c文件
static int i=10; int next() { return(i+=1); } int last() { return(i-=1); } int sum(int i) { static int j=5; return(i=j+=i); }
在file3.c的開頭說明i是外部的,表明它與file1.c定義的i是同一個變量,所以reset的值返回的就是這個i的當前值1。
file3.c文件
extern int i; reset() { return(i); }
具體執行過程分析如下:
附:運行結果
i=1 j=1 next(i)=11 last(i)=10 sum(i+j)=7 i=1 j=2 next(i)=11 last(i)=10 sum(i+j)=10 i=1 j=3 next(i)=11 last(i)=10 sum(i+j)=14
解析static關鍵字
static在c裡面可以用來修飾變量,也可以用來修飾函數。
先看用來修飾變量的時候。變量在c裡面可分為存在全局數據區、棧和堆裡。其實我們平時所說的堆棧是棧而不包含對,不要弄混。
int a; main() { int b ; int c* = (int *)malloc(sizeof(int)); }
a是全局變量,b是棧變量,c是堆變量。
static對全局變量的修飾,可以認為是限制了只能是本文件引用此變量。有的程序是由好多.c文件構成。彼此可以互相引用變量,但加入static修飾之後,只能被本文件中函數引用此變量。
static對棧變量的修飾,可以認為棧變量的生命周期延長到程序執行結束時。一般來說,棧變量的生命周期由OS管理,在退棧的過程中,棧變量的生命也就 結束了。但加入static修飾之後,變量已經不在存儲在棧中,而是和全局變量一起存儲。同時,離開定義它的函數後不能使用,但如再次調用定義它的函數 時,它又可繼續使用, 而且保存了前次被調用後留下的值。
static對函數的修飾與對全局變量的修飾相似,只能被本文件中的函數調用,而不能被同一程序其它文件中的函數調用。