當前位置:才華齋>計算機>C語言>

C語言變數儲存類別和記憶體四區

C語言 閱讀(2.24W)

C語言是一門通用計算機程式語言,應用廣泛。C語言的設計目標是提供一種能以簡易的方式編譯、處理低階儲存器、產生少量的機器碼以及不需要任何執行環境支援便能執行的程式語言。下面我們一起來看看C語言變數儲存類別和記憶體四區的介紹,歡迎大家閱讀!

C語言變數儲存類別和記憶體四區
C語言變數儲存類別和記憶體四區

  變數儲存類別

變數宣告/定義的一般形式:

儲存類別 資料型別 變數名

儲存類別指的是資料在記憶體中儲存的方法。儲存方法分為靜態儲存和動態儲存兩大類。標準C語言為變數、常量和函式定義了4種儲存型別:extern、auto、static、register。根據變數的儲存類別,可以知道變數的作用域和儲存期。這4種儲存型別可分為兩種生存期限:永久的(在整個程式執行期都存在)和臨時的(暫時儲存在堆疊和暫存器中)。extern和static用來標識永久生存期限的“變數和函式”,而anto和register用來標識臨時生存期限的"變數"。只有變數才有臨時生存期限。一個變數和函式只能具有一個儲存型別,也只能有一種生存期限。

記憶體中供使用者使用的空間有三部分:

程式區:存放程式的可執行程式碼;

靜態儲存區:存放靜態變數(全域性變數和靜態區域性變數);

動態儲存區:存放函式呼叫時呼叫函式的現場保護和返回地址、函式形參、自動區域性變數;

變數的宣告分為”定義性宣告“(需建立儲存空間,如:int a;)和”引用性宣告“(不需建立儲存空間,如extern a;)。廣義上講,宣告包括定義,一般為敘述方便,把建立儲存空間的宣告稱定義,而不不需建立儲存空間的宣告稱宣告。

auto

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

對自動變數賦初值,不是在編譯時進行的,而是在函式呼叫時進行。對自動變數來說,若不賦初值,則它的值是一個不確定的值。

int Fun(int a)

{

auto int b, c=3; //定義b和c為整型的自動變數,auto可省略

b = c + a; return b;

}

  register

一般情況下,變數的值是存放在記憶體中的。當程式中用到哪一個變數的值時,由控制器發出指令將記憶體中該變數的值送到CPU中的運算器。經過運算器進行運算,如果需要存數,再從運算器將資料送到記憶體存放。為提高執行效率,C++允許將區域性變數的值放在CPU中的暫存器中,需要用時直接從暫存器取出參加運算,不必再到記憶體中去存取。這種變數叫做暫存器變數,用關鍵字register作宣告。暫存器變數的分配方式是動態分配的。

由於CPU中的通用暫存器數目有限,通常只把少數使用頻繁的變數定義為暫存器變數。對超出暫存器數目的暫存器變數作一般自動變數處理。

只有區域性自動變數和形式引數可作為暫存器變數,其他(如全域性變數、區域性靜態變數等)不行。在程式中定義暫存器變數對編譯系統只是建議性(而不是強制性)的。當今的優化編譯系統能夠識別使用頻繁的變數,自動地將這些變數放在暫存器中。

  extern

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

1) 在一個檔案內宣告全域性變數

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

用extern宣告外部變數時,型別名可寫可不寫。例如," extern int A , B ; " 也可寫成 " extern A , B ; "。

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

如果一個程式包含兩個檔案,在兩個檔案中都要用到同一個外部變數num,不能分別在兩個檔案中各自定義一個外部變數num。正確的做法是:在任一個檔案中定義外部變數num,而在另一檔案中用extern對num作外部變數宣告,即 " extern int num " 或 " extern num ";編譯系統由此知道num是一個已在別處定義的外部變數,它先在本檔案中找有無外部變數num,如果有,則將其作用域擴充套件到本行開始,如果本檔案中無此外部變數,則在程式連線時從其他檔案中找有無外部變數num,如果有,則把在另一檔案中定義的外部變數num的作用域擴充套件到本檔案,在本檔案中可以合法地引用該外部變數num。

  static

所有全域性變數和用關鍵字static作儲存型別說明的區域性變數稱為靜態變數。靜態變數存放在靜態儲存區,一旦為其分配了儲存單元,它們在整個程式執行期間將固定地佔用這些儲存單元。若非必要,不要多用靜態區域性變數。

對全域性變數,static使其區域性化(區域性於本檔案),靜態全域性變數僅能為本原始檔中各函式使用,不能為本原始檔以外的其他原始檔使用。

對區域性變數,static使其由動態儲存變為靜態儲存,靜態區域性變數僅能為本函式使用,其他函式不能使用和影響它們。靜態區域性變數是在編譯時賦初值的',且只賦初值一次。如在定義區域性變數時不賦初值的話,則對靜態區域性變數來說,編譯時自動賦初值0(對數值型變數)或空字元(對字元變數)。

  注:

內部函式也稱靜態函式,不能被其他檔案中的函式使用。定義內部函式時,在函式名和函式型別的前面加static即可。

在C語言中,函式前如果無關鍵字extern,隱含其為外部函式。若需在其他檔案的函式中呼叫此外部函式,只需在呼叫的檔案中用extern宣告該外部函式。

  記憶體四區

棧區(stack)

由編譯器自動分配釋放,存放函式的引數值、區域性變數的值等;其操作方式類似於資料結構中的棧。

堆區(heap)

一般由程式設計師分配釋放(動態記憶體申請與釋放),若程式設計師不釋放,程式結束時可能由作業系統回收。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列。

全域性區/靜態區(static)

全域性變數和靜態變數的儲存是放在一起的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域,該區域在程式結束後由作業系統釋放;

常量區:字串常量和其他常量的儲存位置,程式結束後由作業系統釋放。

程式程式碼區(code)

存放函式的二進位制程式碼。

函式呼叫模型必須和程式四記憶體區綜合起來考慮:

主調函式分配的記憶體(棧區、堆區、全域性區)都可以在被呼叫函式中使用;

被呼叫函式中分配的記憶體,要分情況:在棧區中分配的記憶體,在主調函式中是不能使用的;