動態儲存方式和靜態儲存方式
變數從存在的時間(生存期)角度來分,可以分為動態儲存方式和靜態儲存方式。
所謂靜態儲存方式是指在程式執行開始時由系統分配固定的儲存空間的方式。
動態儲存方式則是在程式執行期間根據需要進行動態的分配儲存空間的方式。
儲存空間分為3部分:(1)程式區(2)靜態儲存區(3)動態儲存區。
在C語言中,每一個變數和函式都有兩個屬性:資料型別和資料的儲存類別。
對資料型(如整型,字元型等):儲存類別指的是資料在記憶體中的儲存方式。具體包含四種:自動的(auto),靜態的(static),暫存器的(register),外部的(extern)。根據變數的儲存類別,可以知道變數的作用域和生存期。
1、auto變數
函式中的區域性變數,如不專門宣告為static儲存類別,都是動態的分配儲存空間(棧),資料儲存在動態儲存區中。
函式中的形參和在函式中定義的變數(包括在複合語句中定義的變數),都屬此類,在呼叫該函式時,系統會給它們分配儲存空間,在函式呼叫結束時,自動釋放這些儲存空間。
例:int f(int a) /*定義為f函式,a為形參*/
{
auto int b,c=3;/*定義b,c為自動變數*/
}
關鍵字auto可以省略,auto不寫則預設為“自動儲存類別”。
2、用stastic宣告區域性變數
有時希望函式中的區域性變數的值在函式呼叫結束後不消失,即儲存單元不釋放。
這時就應指定區域性變數為“靜態區域性變數”,用static進行宣告。
例:
#include <stdafx.h> #include<stdio.h> int f(int a) { auto b=0; static int c=3; b=b+1; c=c+1; return(a+b+c); } void main() { int a=2,i; for(i=0;i<3;i++) { printf("%d\n",f(a)); } }
說明:(1)靜態區域性變數屬於靜態儲存類別,在靜態儲存區內分配儲存單元。在函式整個執行期間都不釋放,而自動變數屬於動態儲存類別,佔動態儲存空間而不佔靜態儲存空間,函式呼叫結束後釋放。
(2)對靜態區域性變數是在編譯時賦初值的,即只賦初值一次,在程式執行時已有初值。
(3)若在定義區域性變數時不賦初值的話,則對靜態區域性變數來說,編譯時自動賦初值0(對數值型變數)或空字元(對字元型變數),對自動變數來說,不賦初值則它的值是一個不確定的值。
(4)雖然靜態區域性變數在函式呼叫結束後仍然存在,但其他函式是不能引用它的。
例:輸出從1到5的階乘值。
#include <stdafx.h> #include<stdio.h> int fac(int a) { static int f=1; f=f*a; return(f); } void main() { int i ; for(i=1;i<=5;i++) { printf("%d!=%d\n",i,fac(i)); } }
3、register變數
一般情況下,變數存放在記憶體中。
但若一些變數使用過於頻繁則會浪費很多時間(cpu處理資料與記憶體讀取資料有時間差)。
為提高程式執行效率,C語言允許將區域性變數的值放在CPU暫存器中,需要時直接取出參加運算,不必再到記憶體中去存取。
這種變數稱為暫存器變數,用關鍵字register作宣告。
例:輸出1到n階乘的值。
#include <stdafx.h> #include<stdio.h> int fac(int n) { static int i ,f=1; for(i=1;i<=n;i++) { f*=i; } return(f); } void main() { int i,n; scanf("%d",&n); for(i=1;i<=n;i++) { printf("%d!=%d\n",i,fac(i)); } }
4、用extern宣告外部變數
有時要用extern來宣告外部變數,以擴充套件外部變數的作用域。
例:
#include <stdafx.h> #include<stdio.h> int max(int x,int y) { int z; z=x>y?x:y; return(z); } void main() { extern int A,B; printf("%d\n",max(A,B)); } int A=13,B=8;
其實extern的作用就是告訴編譯器讀到AB時知道其為全域性變數,其值可能在程式的任意一個地方。