堆與棧是兩種資料結構,並不是一種資料結構,堆是堆,棧是棧。
1、棧:是一種只能在一端進行插入和刪除的資料結構。
允許插入與刪除的一端被稱為棧頂,另一端被稱為棧底。
按照先進後出的順序儲存資料。最先進入的資料存放在棧底,最後進入的資料存放在棧頂。
當棧裡的元素為空時,稱為空棧。
在函式呼叫的時候用於儲存斷點,遞迴的時候,也需要用到棧。
棧一般包含以下兩個方面的資訊:
(1)函式的返回位址和引數。
(2)臨時變數:包括函式的非靜態區域性變數及編譯器自動生成的其他臨時變數。
在組合語言中,棧頂由esp暫存器進行定位,壓棧的操作使得棧頂的位址減小,彈出的操作使得棧頂的位址增大。
2、堆:是一種動態的儲存結構,實際上是資料段中的自由儲存區,常用語儲存、分配動態資料。
堆中存入的資料位址向增加方向變動。
堆可以不斷的進行分配直到沒有堆空間為止,也可以隨時進行釋放、在分配,不存在順序問題。
在c語言中,堆空間的分配通常通過malloc()、calloc()、realloc()三個函式來實現的,而堆的釋放是通過free()函式來進行釋放分配的空間。
3、棧的體驗
如何通過棧將陣列裡面的資料通過print函式列印出來呢?
print函式沒有引數,應該在print函式裡面填充什麼**,可以實現將arr陣列裡面的資料全部列印出來呢?
#include void print(){}int main(); print(); return 0;}
那麼這就涉及到彙編的一些東西了,具體彙編如下:
1、push操作先移動棧頂指標,之後將資訊入棧。
2、eps為棧頂指標,壓棧的操作使得棧頂的位址減小,彈出的操作使得棧頂的位址增大。
3、ebp是32位的bp,是基址指標。bp為基指標暫存器,用它可以直接訪問堆疊中的資料,它在呼叫函式時儲存esp,以便函式結束時可以正確返回。
4、預設的函式內部變數的壓棧操作為:從上到下,從左到右,採用4位元組對齊,陣列壓棧方法略有不同,即從最後乙個元素開始,直到起始元素為止,即採用從右到左的方法壓棧。
在main()函式和print()函式的開頭都有如下兩句彙編指定:
第乙個push指標的操作步驟是,首先移動棧頂指標esp,然後將ebp內容壓棧,注意此時壓棧的ebp的值為上乙個函式的esp的值,而esp恰好就是上乙個函式的棧底。
所以每個函式一開始push指令就是儲存上乙個函式的棧底。
由於esp是當前的棧頂指標,所以該指標的作用就是儲存當前棧頂指標的值。
所以我們只需要在print函式中得到main函式的棧底,就可以去取出陣列中的每乙個元素了。
具體實現方法如下:
void print() int *p = (int *)(*(int *)_ebp - 4 - 4 - 4 - 4 * 7 ); for (int i = 0; i < 7; i++) { printf("%d
什麼是堆 棧
delphi 的屬性太複雜了,先換換思路,再繼續學習.程式需要的記憶體空間分為 heap 堆 和 stack 棧 heap 是自由儲存區,stack 是自動儲存區 使用 heap 需要手動申請 手動釋放,stack 是自動申請 自動釋放 使用 heap 時,如果只申請不釋放,就會發生 記憶體洩露 不...
什麼是堆疊,有什麼區別
堆疊都是一種資料項按序排列的資料結構,只能在一端 稱為棧頂 top 對資料項進行插入和刪除。要點 堆 順序隨意 棧 後進先出 last in first out 一 預備知識 程式的記憶體分配 乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器 自動分配釋放 存放函...
函式幀的esp與ebp操作
每乙個函式都有乙個函式幀 就是以ebp為基位址,esp為頂位址 而函式之間的呼叫會出現幀的切換,這時用到了兩個暫存器,esp與ebp,那麼它們的作用與關心是怎樣的呢 由兩句話可知 esp 棧 頂 指標,始終指向棧頂,當遇到push pop call ret等指令時它會改變,因此,程式設計師使用它來進...