程式的虛擬位址空間分為多個區域,棧(stack)是其中位址較高的乙個區域。棧(stack)可以存放函式引數、區域性變數、區域性陣列等作用範圍在函式內部的資料,它的用途就是完成函式的呼叫。
棧記憶體由系統自動分配和釋放:發生函式呼叫時就為函式執行時用到的資料分配記憶體,函式呼叫結束後就將之前分配的記憶體全部銷毀。所以區域性變數、引數只在當前函式中有效,不能傳遞到函式外部。
在計算機中,棧可以理解為乙個特殊的容器,使用者可以將資料依次放入棧中,然後再將資料按照相反的順序從棧中取出。也就是說,先放入的資料最後才能取出,而最後放入的資料必須先取出。這稱為先進後出(first in last out)原則。
放入資料常稱為入棧或壓棧(push),取出資料常稱為出棧或彈出(pop)。如下圖所示:
可以發現,棧底始終不動,出棧入棧只是在移動棧頂,當棧中沒有資料時,棧頂和棧底重合。
從本質上來講,棧是一段連續的記憶體,需要同時記錄棧底和棧頂,才能對當前的棧進行定位。在現代計算機中,通常使用ebp
暫存器指向棧底,而使用esp
暫存器指向棧頂。隨著資料的進棧出棧,esp 的值會不斷變化,進棧時 esp 的值減小,出棧時 esp 的值增大。
ebp 和 esp 都是cpu中的暫存器:ebp 是 extend base pointer 的縮寫,通常用來指向棧底;esp 是 extend stack pointer 的縮寫,通常用來指向棧頂。
如下圖所示是乙個棧的例項:
對每個程式來說,棧能使用的記憶體是有限的,一般是 1m~8m,這在編譯時就已經決定了,程式執行期間不能再改變。如果程式使用的棧記憶體超出最大值,就會發生棧溢位(stack overflow)錯誤。
乙個程式可以包含多個執行緒,每個執行緒都有自己的棧,嚴格來說,棧的最大值是針對執行緒來說的,而不是針對程式。
棧記憶體的大小和編譯器有關,編譯器會為棧記憶體指定乙個最大值,在 vc/vs 下,預設是 1m,在 c-free 下,預設是 2m,在 linux gcc 下,預設是 8m。
當然,我們也可以通過引數來修改棧記憶體的大小。以 vs2010 為例,在工程名處右擊,會彈出乙個選單,選擇「屬性」,會出現乙個對話方塊,如下圖所示:
}區域性字元陣列 str 儲存在棧上,占用 2m 的記憶體,超出了預設值 1m,所以會發生棧溢位錯誤,如下圖所示:
棧的概念以及棧溢位
對每個程式來說,棧能使用的記憶體是有限的,一般是 1m 8m,這在編譯時就已經決定了,程式執行期間不能再改變。如果程式使用的棧記憶體超出最大值,就會發生棧溢位 stack overflow 錯誤。乙個程式可以包含多個執行緒,每個執行緒都有自己的棧,嚴格來說,棧的最大值是針對執行緒來說的,而不是針對程...
記憶體中堆和棧的區別,以及C語言中的記憶體模型
c語言的記憶體模型分為5個區 棧區 堆區 靜態區 常量區 區。每個區儲存的內容如下 1 棧區 存放函式的引數值 區域性變數等,由編譯器自動分配和釋放,通常在函式執行完後就釋放了,其操作方式類似於資料結構中的棧。棧記憶體分配運算內置於cpu的指令集,效率很高,但是分配的記憶體量有限,比如ios中棧區的...
c語言棧的實現以及操作
此文章包含了棧的結構體實現,單資料型別實現,以及清空,判空,入棧,出棧,求棧頂元素的實現 棧作為乙個最簡單的資料結構,實現起來也非常容易,想想現在有一摞盤子,每次只能取走或放乙個盤子且只能最上面進行操作 那麼我們如果有乙個索引top時刻指向最上面的那個盤子,棧不就實現了麼?第一段是單資料型別的 in...