C語言變量存儲類別和內存四區

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)

存放函數的二進制代碼。

函數調用模型必須和程序四內存區綜合起來考慮:

主調函數分配的內存(棧區、堆區、全局區)都可以在被調用函數中使用;

被調用函數中分配的內存,要分情況:在棧區中分配的內存,在主調函數中是不能使用的;