1. 程式人生 > >區域性變數、全域性變數、堆、堆疊、靜態和全域性的區別

區域性變數、全域性變數、堆、堆疊、靜態和全域性的區別

一般全域性變數存放在資料區,區域性變數存放在棧區,動態變數存放在堆區,函式程式碼放在程式碼區。

棧區是普通的棧資料結構,遵循LIFO後進先出的規則,區域性變數安排在那裡是ASM時就規定的,這樣可以在一個函式結束後平衡堆疊,操作簡單,效率高堆(動態區)在這裡應當叫堆疊(不要和資料結構中的堆搞混)是程式在編譯時產生的一塊用於產生動態記憶體分配使用的塊,操作比較棧要麻煩許多,在分配時要判斷最優的地址(防止產生無用的記憶體碎片(由於屢次的NEWDELETE產生的夾在兩塊使用中記憶體中的空餘小記憶體(不容易被分配))),分配和回收時的效率比棧低多了棧是系統提供的功能,特點是快速高效,缺點是有限制,資料不靈活;而棧是函式庫提供的功能,特點是靈活方便,資料適應面廣泛,但是效率

>有一定降低。棧是系統資料結構,對於程序/執行緒是唯一的;堆是函式庫內部資料結構,不一定唯一。不同堆分配的記憶體無法互相操作。

棧空間分靜態分配和動態分配兩種。靜態分配是編譯器完成的,比如自動變數(auto)的分配。動態分配由alloca函式完成。棧的動態分配無需釋放(是自動的),也就沒有釋放函式。為可移植>的程式起見,棧的動態分配操作是不被鼓勵的!堆空間的分配總是動態的,雖然程式結束時所有的資料空間都會被釋放回系統,但是精確的申請記憶體/釋放記憶體匹>配是良好程式的基本要素。這是我對堆與棧收藏內容~堆是程式設計師管理的,棧是系統管理的.

另外關於靜態和全域性的一些問題:

靜態變數的特點:

1、一次儲存:靜態區域性變數只被初始化一次,下一次初始化根據上一次的結果值,有點類似於c++中類的靜態成員變數,即無論該型別生成多少個例項物件,所有的物件共用一個靜態變數,到這裡就是無論這個函式呼叫多少次,該靜態變數只初始化一次,並沒有因為超出其生存期而被銷燬,只是外部不可見而已,用個例子說明之:

void fun1(int v)
{
    static int value=v;
    static int value=v;
}

int main(int arc,char*args[])
{
    fun1(50);
    fun1(100);
}


執行的結果是:value:50 value:50說明在第二次呼叫

fun1()時的初始化value的採用的是上一次value的值,value在靜態區的儲存空間並沒有因為fun1()的結束而被釋放,即體現了一次儲存;

2、作用域限定:靜態修飾的作用域限定功能同時體現在函式與變數上;

a)對於函式而言,任何用static修飾的函式,其作用域僅為當前原始檔,而對外部來說這個函式是不可見的,即只有和其在同一原始檔中的函式才能呼叫這個靜態函式;反過來說,如果一個函式僅僅被同一原始檔中的其他函式呼叫,那麼這個函式應該宣告為靜態的,這樣做的好處在於:可以一定程度上的解決不同原始檔之間函式的命名衝突問題;

b)對於變數而言,static修飾的全域性變數,只在當前原始檔中有效,對外部不可見,外部檔案不能夠引用;

顧名思義,全域性變數是指能夠在全域性引用的變數,相對於區域性變數的概念,也叫外部變數;同靜態變數一樣,全域性變數位於靜態資料區,全域性變數一處定義,多處引用,用關鍵字“extern”引用外部的變數。

全域性變數也可以是靜態的,在前面有過說明,靜態全域性變數的意義就是不讓外部引用,是單個原始檔裡的全域性變數,即是編譯階段的全域性變數,而不是連線階段的全域性變數。

通過上面的分析,我們不難得出以下結論:

1、靜態函式與普通函式的區別在於:靜態函式不可以被同一原始檔以外的函式呼叫。

2、靜態區域性變數與普通區域性變數的區別在於:靜態區域性變數只初始化一次,下一次初始化實際上是依然是上一次的變數;

3、靜態全域性變數與普通全域性變數的區別在於:靜態全域性變數的作用域僅限於所在的原始檔。