C C 中堆疊的那些事

2021-08-15 16:00:56 字數 1458 閱讀 7551

前言:

堆疊是一種具有「後進先出」(lifo---last in first out)特殊訪問屬性的儲存結構。堆

棧一般使用ram 物理資源作為儲存體,再加上lifo 訪問介面實現。

為什麼棧向下增長?

「這個問題與虛擬位址空間的分配規則有關,每乙個可執行c程式,從低位址到高位址依次是:text,data,bss,堆,棧,環境引數變數;其中堆和棧之間有很大的位址空間空閒著,在需要分配空間的時候,堆向**,棧往下漲。」

這樣設計可以使得堆和棧能夠充分利用空閒的位址空間。如果棧向**的話,我們就必須得指定棧和堆的乙個嚴格分界線,但這個分界線怎麼確定呢?平均分?但是有的程式使用的堆空間比較多,而有的程式使用的棧空間比較多。所以就可能出現這種情況:乙個程式因為棧溢位而崩潰的時候,其實它還有大量閒置的堆空間呢,但是我們卻無法使用這些閒置的堆空間。所以呢,最好的辦法就是讓堆和棧乙個向**,乙個向下漲,這樣它們就可以最大程度地共用這塊剩餘的位址空間,達到利用率的最大化!!

為什麼要把堆和棧分開?

為什麼要把堆和棧區分出來呢?棧中不是也可以儲存資料嗎?

第一,從軟體設計的角度看,棧代表了處理邏輯,而堆代表了資料。

這樣分開,使得處理邏輯更為清晰。分而治之的思想。這種隔離、模組化的思想在軟體設計的方方面面都有體現。

第二,堆與棧的分離,使得堆中的內容可以被多個棧共享(也可以理解為多個執行緒訪問同乙個物件)。這種共享的收益是很多的。一方面這種共享提供了一種有效的資料互動方式(如:共享記憶體),另一方面,堆中的共享常量和快取可以被所有棧訪問,節省了空間。

第三,棧因為執行時的需要,比如儲存系統執行的上下文,需要進行位址段的劃分。由於棧只能向上增長,因此就會限制住棧儲存內容的能力。而堆不同,堆中的物件是可以根據需要動態增長的,因此棧和堆的拆分,使得動態增長成為可能,相應棧中只需記錄堆中的乙個位址即可。

第四,物件導向就是堆和棧的完美結合。其實,物件導向方式的程式與以前結構化的程式在執行上沒有任何區別。但是,物件導向的引入,使得對待問題的思考方式發生了改變,而更接近於自然方式的思考。當我們把物件拆開,你會發現,物件的屬性其實就是資料,存放在堆中;而物件的行為(方法),就是執行邏輯,放在棧中。我們在編寫物件的時候,其實即編寫了資料結構,也編寫的處理資料的邏輯。不得不承認,物件導向的設計,確實很美。

///乙個由c/c++編譯的程式占用的記憶體分為以下幾個部分

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

2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由os** 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶,呵呵。

3、全域性區(靜態區)(static)—,全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 - 程式結束後有系統釋放

4、文字常量區 —常量字串就是放在這裡的。 程式結束後由系統釋放

5、程式**區—存放函式體的二進位制**。

C C 分配記憶體的那些事

首先需要知道,編譯器給變數分配的記憶體分為三部分 靜態儲存區域 棧 堆。靜態儲存區 主要儲存全域性變數和靜態變數。棧 呼叫函式相關的變數 位址等,底層對棧提供支援,棧的大小遠小於堆的大小,向負方向生長,限定大小。堆 儲存動態生成的變數,操作由c c 函式庫提供,效率低於棧,向正方向生長,無限大小 3...

C C 和指標 printf 的那些事

一,printf 1 作用 產生格式化輸出的函式 定義在 stdio.h 中 2 用法 int printf const char format,argument format 引數輸出的格式,定義格式為 flags width perc f n h l type 規定資料輸出方式,具體如下 1.t...

c c 中堆疊的區別

這個文章不錯,所以轉一下!共冕!一直就搞不清出這個問題,今天上網想起來,隨即搜了搜,找到了一些資料。不知源作者是誰。姑且 拿來主義 一下,呵呵。一 預備知識 程式的記憶體分配 乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放 存放函式的引數值,區域性變...