C 變數的儲存類別

2021-08-14 18:54:06 字數 4375 閱讀 5756

上一節已介紹了變數的一種屬性——作用域,作用域是從空間的角度來分析的,分為全域性變數和區域性變數。

變數還有另一種屬性——儲存期(storage duration,也稱生命期)。儲存期是指變數在記憶體中的存在期間。這是從變數值存在的時間角度來分析的。儲存期可以分為靜態儲存期(static storage duration)和動態儲存期(dynamic storage duration)。這是由變數的靜態儲存方式和動態儲存方式決定的。

所謂靜態儲存方式是指在程式執行期間,系統對變數分配固定的儲存空間。

而動態儲存方式則是在程式執行期間,系統對變數動態地分配儲存空間。

先看一下記憶體中的供使用者使用的儲存空間的情況。這個儲存空間可以分為三部分,即:

(1) 程式區

(2) 靜態儲存區

(3) 動態儲存區

資料分別存放在靜態儲存區和動態儲存區中。全域性變數全部存放在靜態儲存區中,在程式開始執行時給全域性變數分配儲存單元,程式執行完畢就釋放這些空間。在程式執行過程中它們佔據固定的儲存單元,而不是動態地進行分配和釋放。

在動態儲存區中存放以下資料:

①函式形式引數。在呼叫函式時給形參分配儲存空間。

②函式中的自動變數(未加static宣告的區域性變數,詳見後面的介紹)。

③函式呼叫時的現場保護和返回位址等。

對以上這些資料,在函式呼叫開始時分配動態儲存空間,函式結束時釋放這些空間。在程式執行過程中,這種分配和釋放是動態的,如果在乙個程式中兩次呼叫同一函式,則要進行兩次分配和釋放,而兩次分配給此函式中區域性變數的儲存空間位址可能是不相同的。

如果在乙個程式中包含若干個函式,每個函式中的區域性變數的儲存期並不等於整個程式的執行週期,它只是整個程式執行週期的一部分。根據函式呼叫的情況,系統對區域性變數動態地分配和釋放儲存空間。

在c++中變數除了有資料型別的屬性之外,還有儲存類別(storage class) 的屬性。儲存類別指的是資料在記憶體中儲存的方法。

儲存方法分為靜態儲存和動態儲存兩大類。具體包含4種:自動的(auto)、靜態的(static)、暫存器的(register)和外部的(extern)。根據變數的儲存類別,可以知道變數的作用域和儲存期。

函式中的區域性變數,如果不用關鍵字static加以宣告,編譯系統對它們是動態地分配儲存空間的。函式的形參和在函式中定義的變數(包括在復合語句中定義的變數)都屬此類。在呼叫該函式時,系統給形參和函式中定義的變數分配儲存空間,資料儲存在動態儲存區中。在函式呼叫結束時就自動釋放這些空間。如果是在復合語句中定義的變數,則在變數定義時分配儲存空間,在復合語句結束時自動釋放空間。

因此這類區域性變數稱為自動變數(auto variable)。自動變數用關鍵字auto作儲存類別的宣告。

例如:int f(int a) //定義f函式,a為形參

儲存類別auto和資料型別int的順序任意。關鍵字auto可以省略,如果不寫auto,則系統把它預設為自動儲存類別,它屬於動態儲存方式。

程式中大多數變數屬於自動變數。本書前面各章所介紹的例子中,在函式中定義的變數都沒有宣告為auto,其實都預設指定為自動變數。在函式體中以下兩種寫法作用相同:

① auto int b,c=3;

② int b,c=3;

有時希望函式中的區域性變數的值在函式呼叫結束後不消失而保留原值,即其占用的儲存單元不釋放,在下一次該函式呼叫時,該變數保留上一次函式呼叫結束時的值。

這時就應該指定該區域性變數為靜態區域性變數(static local variable)。

例4.12 靜態區域性變數的值。

#include

using namespace std;

int f(int a)  //定義f函式,a為形參

int main( )

執行結果為

7 8 9

先後3次呼叫f函式時,b和c的值如書中表4.1所示。

對靜態區域性變數的說明:

靜態區域性變數在靜態儲存區內分配儲存單元。在程式整個執行期間都不釋放。而自動變數(即動態區域性變數)屬於動態儲存類別,儲存在動態儲存區空間(而不是靜態儲存區空間),函式呼叫結束後即釋放。

為靜態區域性變數賦初值是在編譯時進行值的,即只賦初值一次,在程式執行時它已有初值。以後每次呼叫函式時不再重新賦初值而只是保留上次函式呼叫結束時的值。而為自動變數賦初值,不是在編譯時進行的,而是在函式呼叫時進行,每呼叫一次函式重新給一次初值,相當於執行一次賦值語句。

如果在定義區域性變數時不賦初值的話,對靜態區域性變數來說,編譯時自動賦初值0(對數值型變數)或空字元(對字元型變數)。而對自動變數來說,如果不賦初值,則它的值是乙個不確定的值。這是由於每次函式呼叫結束後儲存單元已釋放,下次呼叫時又重新另分配儲存單元,而所分配的單元中的值是不確定的。

雖然靜態區域性變數在函式呼叫結束後仍然存在,但其他函式是不能引用它的,也就是說,在其他函式中它是「不可見」的。

在什麼情況下需要用區域性靜態變數呢?

需要保留函式上一次呼叫結束時的值。例如可以用下例中的方法求n!。

例4.13 輸出1~5的階乘值(即1!,2!,3!,4!,5!)。

#include

using namespace std;

int fac(int);  //函式宣告

int main( )

定義f和i是存放在暫存器的區域性變數,如果n的值大,則能節約許多執行時間。

在程式中定義暫存器變數對編譯系統只是建議性(而不是強制性)的。當今的優化編譯系統能夠識別使用頻繁的變數,自動地將這些變數放在暫存器中。

全域性變數(外部變數)是在函式的外部定義的,它的作用域為從變數的定義處開始,到本程式檔案的末尾。在此作用域內,全域性變數可以為本檔案中各個函式所引用。編譯時將全域性變數分配在靜態儲存區。

有時需要用extern來宣告全域性變數,以擴充套件全域性變數的作用域。

1. 在乙個檔案內宣告全域性變數

如果外部變數不在檔案的開頭定義,其有效的作用範圍只限於定義處到檔案終了。如果在定義點之前的函式想引用該全域性變數,則應該在引用之前用關鍵字extern對該變數作外部變數宣告,表示該變數是乙個將在下面定義的全域性變數。有了此宣告,就可以從宣告處起,合法地引用該全域性變數,這種宣告稱為提前引用宣告。

例4.14 用extern對外部變數作提前引用宣告,以擴充套件程式檔案中的作用域。

#include

using namespace std;

int max(int,int);  //函式宣告

void main( )

int a=15,b=-7;//定義全域性變數a,b

int max(int x,int y)

執行結果如下:

15在main後面定義了全域性變數a,b,但由於全域性變數定義的位置在函式main之後,因此如果沒有程式的第5行,在main函式中是不能引用全域性變數a和b的。現在我們在main函式第2行用extern對a和b作了提前引用宣告,表示a和b是將在後面定義的變數。這樣在main函式中就可以合法地使用全域性變數a和b了。如果不作extern宣告,編譯時會出錯,系統認為a和b未經定義。一般都把全域性變數的定義放在引用它的所有函式之前,這樣可以避免在函式中多加乙個extern宣告。

2. 在多檔案的程式中宣告外部變數

如果乙個程式包含兩個檔案,在兩個檔案中都要用到同乙個外部變數num,不能分別在兩個檔案中各自定義乙個外部變數num。正確的做法是:在任乙個檔案中定義外部變數num,而在另一檔案中用extern對num作外部變數宣告。即

extern int num;

編譯系統由此知道num是乙個已在別處定義的外部變數,它先在本檔案中找有無外部變數num,如果有,則將其作用域擴充套件到本行開始(如上節所述),如果本檔案中無此外部變數,則在程式連線時從其他檔案中找有無外部變數num,如果有,則把在另一檔案中定義的外部變數num的作用域擴充套件到本檔案,在本檔案中可以合法地引用該外部變數num。

分析下例:

file1.cppfile2.cpp

extern int a,b;  int a=3,b=4;

int main( )  ┆

用extern擴充套件全域性變數的作用域,雖然能為程式設計帶來方便,但應十分慎重,因為在執行乙個檔案中的函式時,可能會改變了該全域性變數的值,從而會影響到另一檔案中的函式執行結果。

有時在程式設計中希望某些外部變數只限於被本檔案引用,而不能被其他檔案引用。這時可以在定義外部變數時加乙個static宣告。例如:

file1.cppfile2.cpp

static int a=3;extern int a;

int main ( )  int fun (int n)

}這種加上static宣告、只能用於本檔案的外部變數(全域性變數)稱為靜態外部變數。這就為程式的模組化、通用性提供了方便。如果已知道其他檔案不需要引用本檔案的全域性變數,可以對本檔案中的全域性變數都加上static,成為靜態外部變數,以免被其他檔案誤用。

需要指出,不要誤認為用static宣告的外部變數才採用靜態儲存方式(存放在靜態儲存區中),而不加static的是動態儲存(存放在動態儲存區)。實際上,兩種形式的外部變數都用靜態儲存方式,只是作用範圍不同而已,都是在編譯時分配記憶體的。

參考:

C語言變數儲存類別

變數除了型別屬性 int char float.外,另外乙個重要屬性就是儲存類別 系統把程式中用到的資料區分為靜態儲存區和動態儲存區。靜態儲存區 在這個區分配了空間的變數,在程式執行過程中一直存在,即相對是不變的。動態儲存區 在這個區分配了空間的變數,可能隨時被釋放,即相對是不斷變化的。c語言提供了...

C語言變數的儲存類別

前面已經介紹了,從變數的作用域 即從空間 角度來分,可以分為全域性變數和區域性變數。從另乙個角度,從變數值存在的作時間 即生存期 角度來分,可以分為 靜態儲存方式 和動態儲存方式。使用者儲存空間可以分為三個部分 程式區 靜態儲存區 動態儲存區。全域性變數全部存放在靜態儲存區,在程式開始執行時給全域性...

c語言 變數的儲存類別

1.動態儲存方式與靜態儲存方式 執行結果 1 函式中的區域性變數 形參 在函式中定義的變數等 如果不專門宣告為static儲存類別,都是動態分配儲存空間的,在函式呼叫時系統給這些變數分配空間,在呼叫結束時系統就自動釋放這些記憶體空間,因此這類區域性變數被稱為自動變數。2 實際上,關鍵字 auto 可...