什麼是堆和棧?函式壓棧是怎麼回事

2021-05-22 14:16:05 字數 5586 閱讀 9201

1樓:匿名使用者

什麼是堆和棧?

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

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

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

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

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

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

函式壓棧是怎麼回事?

函式壓棧的本質是引數傳遞

這又跟組合語言連繫起來了.組合語言的過程即proc可以理解成函式

比如一個最簡單的計算兩數之和函式

如果用匯編來寫估計是這樣的

sub proc

pop ax ;從stack取a 並放在ax暫存器中

pop bx ;從stack取b 並放在bx暫存器中

add ax,bx ; 計算a+b

ret //返回

sub endp

顯然要呼叫這個函式,你應當先把b值push進stack,然後再push a

因為stack是先進後出的

所以呼叫匯編像這樣

比如計算4+5

push 5;

push 4;

call sub; //返回值在ax中

在這個例子中先壓5或先壓4得到的結果沒有變化

但大多數程式,如果引數的順序錯誤將是災難性的

因為不管什麼高階語言最終都要編譯成組合語言,然後是機器語言

同樣下面這個c程式,計算a+b值,必然會編譯成上面的彙編**

int sub(int a ,int b)

所以c在呼叫這個函式sub時,必須要壓棧(即傳入引數)但這些工作,在c語言裡,並不需要你來完成.你只要寫出

sub(7,9);

編譯器在編譯成彙編時就會自動完成相關的壓棧工作.

根據函式呼叫方式和引數壓入順序目前存在三種約定:

stdcall

cdecl

fastcall

這都相關壓棧順序和棧的清理工作約定

他們的細節都不相同,但有一點是肯定的,引數比須從右向左壓入棧中

stdcall中 函式必須自已清理棧

cdecall 由呼叫者清除堆疊 c的預設函式呼叫方式 所以這樣c支援可變引數

fastcall 是把函式引數列表的前三個引數放入暫存器eax,edx,ecx,其他引數壓棧

源**:

int function(int a, int b)

void main()

1.__cdecl

_function

push ebp

mov ebp, esp

mov eax, [ebp+8] ;引數1

add eax, [ebp+c] ;加上引數2

pop ebp

retn

_main

push ebp

mov ebp, esp

push 14h ;引數 2入棧

push 0ah ;引數 1入棧

call _function ;呼叫函式

add esp, 8 ;修正棧

xor eax, eax

pop ebp

retn

2.__fastcall

@function@8

push ebp

mov ebp, esp ;儲存棧指標

sub esp, 8 ;多了兩個區域性變數

mov [ebp-8], edx ;儲存引數 2

mov [ebp-4], ecx ;儲存引數 1

mov eax, [ebp-4] ;引數 1

add eax, [ebp-8] ;加上引數 2

mov esp, ebp ;修正棧

pop ebp

retn

_main

push ebp

mov ebp, esp

mov edx, 14h ;引數 2給edx

mov ecx, 0ah ;引數 1給ecx

call @function@8 ;呼叫函式

xor eax, eax

pop ebp

retn

3.__stdcall

_function@8

push ebp

mov ebp, esp

mov eax, [ebp] ;引數 1

add eax, [ebp+c] ;加上引數 2

pop ebp

retn 8 ;修復棧

_main

push ebp

mov ebp, esp

push 14h ;引數 2入棧

push 0ah ;引數 1入棧

call _function@8 ;函式呼叫

xor eax, eax

pop ebp

retn

2樓:匿名使用者

堆 heap

棧 stack

是兩種不同的資料結構

stack的特點是先入後出 就像疊盤子 先放上去的盤子後拿走(底裡的抽不出來自然最後才能拿走)

stack和heap放在一起討論的話 其實不是講的資料結構了 是說作業系統給程式分配記憶體的方式

對於一個程式來說 執行的時候 系統分配了一定記憶體給它 其中一塊叫堆 一塊叫棧

堆裡面主要放 動態分配的內容 比如c裡面用 malloc 分配到的空間 就在堆裡 c++裡面用new 分配到的也在堆裡

棧裡面放 函式的區域性變數

一個函式的區域性變數 會在這個函式被呼叫時push到棧裡 這個函式返回的時候才從棧裡面pop出來

棧的先入後出的順序使得函式可以巢狀 遞迴 如果遞迴層數太多 棧也會滿 就會出現棧溢位……

c語言中的棧、堆是什麼?

3樓:地面離家出走

c語言中的堆和棧都是一種資料項按序排列的資料結構。

棧就像裝資料的桶或箱子

我們先從大家比較熟悉的棧說起吧,它是一種具有後進先出性質的資料結構,也就是說後存放的先取,先存放的後取。

這就如同我們要取出放在箱子裡面底下的東西(放入的比較早的物體),我們首先要移開壓在它上面的物體(放入的比較晚的物體)。

堆像一棵倒過來的樹

而堆就不同了,堆是一種經過排序的樹形資料結構,每個結點都有一個值。

通常我們所說的堆的資料結構,是指二叉堆。堆的特點是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。

由於堆的這個特性,常用來實現優先佇列,堆的存取是隨意,這就如同我們在圖書館的書架上取書。

雖然書的擺放是有順序的,但是我們想取任意一本時不必像棧一樣,先取出前面所有的書,書架這種機制不同於箱子,我們可以直接取出我們想要的書。

4樓:匿名使用者

堆疊是一種執行「後進先出」演算法的資料結構。

設想有一個直徑不大、一端開口一端封閉的竹筒。有若干個寫有編號的小球,小球的直徑比竹筒的直徑略小。現在把不同編號的小球放到竹筒裡面,可以發現一種規律:

先放進去的小球只能後拿出來,反之,後放進去的小球能夠先拿出來。所以「先進後出」就是這種結構的特點。

堆疊就是這樣一種資料結構。它是在記憶體中開闢一個儲存區域,資料一個一個順序地存入(也就是「壓入——push」)這個區域之中。有一個地址指標總指向最後一個壓入堆疊的資料所在的資料單元,存放這個地址指標的暫存器就叫做堆疊指示器。

開始放入資料的單元叫做「棧底」。資料一個一個地存入,這個過程叫做「壓棧」。在壓棧的過程中,每有一個資料壓入堆疊,就放在和前一個單元相連的後面一個單元中,堆疊指示器中的地址自動加1。

讀取這些資料時,按照堆疊指示器中的地址讀取資料,堆疊指示器中的地址數自動減 1。這個過程叫做「彈出pop」。如此就實現了後進先出的原則。

堆疊是計算機中最常用的一種資料結構,比如函式的呼叫在計算機中是用堆疊實現的。

堆疊可以用陣列儲存,也可以用以後會介紹的連結串列儲存。

下面是一個堆疊的結構體定義,包括一個棧頂指標,一個資料項陣列。棧頂指標最開始指向-1,然後存入資料時,棧頂指標加1,取出資料後,棧頂指標減1。

#define max_size 100

typedef int data_type;

struct stack

; 在c++中,記憶體分成5個區,他們分別是堆、棧、自由儲存區、全域性/靜態儲存區和常量儲存區。

棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的儲存區。裡面的變數通常是區域性變數、函式引數等。

堆,就是那些由new分配的記憶體塊,他們的釋放編譯器不去管,由我們的應用程式去控制,一般一個new就要對應一個delete。如果程式設計師沒有釋放掉,那麼在程式結束後,作業系統會自動**。

自由儲存區,就是那些由malloc等分配的記憶體塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。

全域性/靜態儲存區,全域性變數和靜態變數被分配到同一塊記憶體中,在以前的c語言中,全域性變數又分為初始化的和未初始化的,在c++裡面沒有這個區分了,他們共同佔用同一塊記憶體區。

常量儲存區,這是一塊比較特殊的儲存區,他們裡面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改,而且方法很多.

5樓:圈圈叉叉叉叉圈

在c/c++中,記憶體分成5個區,他們分別是堆、棧、自由

儲存區、全域性/靜態儲存區和常量儲存區。

如果你的這兩個語句是出現在全域性部分,那這個i就是被儲存在全域性/靜態儲存區;如果是出現在區域性某個函式裡,那i就被儲存的棧裡面。具體可以怎麼理解?

棧裡的東西自動分配記憶體空間,自動釋放記憶體,而堆裡面的東西只要是用到記憶體的都要手動分配,malloc函式在這個時候就起作用了。

棧:就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的儲存區。裡面的變數通常是區域性變數、函式引數等。

堆:就是那些由new分配的記憶體塊,他們的釋放編譯器不去管,由我們的應用程式去控制,一般一個new就要對應一個delete。如果程式設計師沒有釋放掉,那麼在程式結束後,作業系統會自動**。

自由儲存區:就是那些由malloc等分配的記憶體塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。

頭痛顱壓高是怎麼回事

是線性表,用的是c語言,演算法嘛說不上什麼的。主要都是一些線性表的操作,比如t ch char malloc s1 length s2 length sizeof char 分配記憶體空間給它,在如if t ch free t ch 釋放記憶體空間,等等。既然你看了資料結構就肯定知道線性表了,線性表...

血小板壓積PCT偏高是怎麼回事

你應該是一位女性吧,女性一般是這樣的,如果超出參考值範圍不多,就不用管它。pct血小板壓積偏低怎麼辦?2008 8 1 20 44 最佳答案 1.紅細胞分佈寬度標準差38.1,偏低。這個值臨床意義較小,不如它的另一個引數用的多 紅細胞分佈寬度cv 如果這個值在正常範圍內,說明紅細胞按體積分佈還是比較...

小豬睡覺堆在一起是怎麼回事

小豬跑,說明小豬非常靈敏健康,沒有疾病的表現。為什麼這樣說呢?因為小豬對新鮮事物比較好奇,經常是這邊聞一聞,那邊嗅一嗅的,然後為了搶東西迅速奔跑,有時甚至還會互相進行打鬥!一些養豬戶們採用掛飼料棒的方法,調教仔豬吃食教槽料,其實就是利用仔豬對新鮮事物的好奇心理!仔豬的疾病大多數是腸道消化問題,比如腹...