堆棧的定義:
堆棧是一種數據結構,具體是一個特定的存儲區或寄存器。堆棧都是一種數據項按序排列的數據結構。只能在一端(稱為棧頂(top))對數據項進行插入和刪除,也就是它的一端是固定的,另一端(棧頂)是浮動的 ,嚴格按照“先進后出”的原則存取,位於其中間的元素,必須在其棧上部(后進棧者)諸元素逐個移出后才能取出。因而棧頂地址總是小於等於棧的基地址。
堆棧的區別:
棧區:存放自動變量。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元由編譯器自動釋放。棧存放函數的參數值,局部變量的值等。
堆區(自由存儲區):在運行的時候調用程序(如C中的malloc或C++中的new)分配內存,可以在任何時候決定分配內存及分配的大小,用戶自己負責在何時釋放內存(如用free或delete)。堆中的所有東西都是匿名的,這樣不能按名字訪問,而只能通過指針訪問。
申請方式:
棧區:由系統自動分配。 例如,聲明在函數中一個局部變量 int b; 系統自動在棧中為b開辟空間。
堆區:需要程序員自己申請,並指明大小,在c中malloc函數
如p = (char *)malloc(10);但是注意p本身是在棧中的。
申請后系統的響應:
棧區:只要棧的剩余空間大於所申請空間,系統將為程序提供內存,否則將報異常提堆區:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然后將該結點從空閑結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多余的那部分重新放入空閑鏈表中。
申請大小的限制:
棧區:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。
堆區:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
申請效率的比較:
棧區:棧由系統自動分配,速度較快。但程序員是無法控制的。
堆區:堆由new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便。另外,在WINDOWS下,最好的方式是用VirtualAlloc分配內存,他不是在堆,也不是在棧是直接在進程的地址空間中保留一快內存,雖然用起來最不方便。但是速度快,也最靈活。
堆和棧中的存儲內容:
棧區:在函數調用時,第一個進棧的是主函數中后的下一條指令(函數調用語句的下一條可執行語句)的地址,然后是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然后是函數中的局部變量。注意靜態變量是不入棧的。當本次函數調用結束后,局部變量先出棧,然后是參數,最后棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆區:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。
存取效率的比較:
棧區:char *s2 = “bbbbbbbbbbbbbbbbb”;bbbbbbbbbbb是在編譯時就確定的;要先把指針值讀到edx中,在根據edx讀取字符,顯然慢了。然而,在棧上的數組比指針所指向的字符串(例如堆)快。
堆區:char s1[] = “aaaaaaaaaaaaaaa”; aaaaaaaaaaa是在運行時刻賦值的;讀取時直接就把字符串中的元素讀到寄存器cl中,顯然比較快。
• 在內存儲器(隨機存儲器)中開辟一個區域作為堆棧,叫軟件堆棧;用寄存器構成的堆棧,叫硬件堆棧。
• 單片機應用中,堆棧是個特殊存儲區,堆棧屬於RAM空間的一部分,堆棧堆棧中的物體具有一個特性:第一個放入堆棧中的物體總是被最后拿出來, 這個特性通常稱為先進后出(FILO—First-In/Last-Out)。 堆棧中定義了一些操作, 兩個最重要的是PUSH和POP。
堆棧的操作
• PUSH(入棧)操作:將數據存放到堆棧中。堆棧指針(SP)加1,然后在堆棧的頂部加入一 個元素。
• POP(出棧)操作:從堆棧中彈出數據。先將SP所指示的內部 ram單元中內容送入直接地址尋址的單元中(目的位置),然后再將堆棧指針(SP)減1。這兩種操作實現了數據項的插入和刪除。
3、堆棧長度:棧空間的大小
4、棧底(Bottom):棧底指向的是堆棧段中地址最大的字單元。
5、棧頂(Top):棧頂是堆棧指針SP指向的位置。當前棧頂字單元的邏輯地址為 SS:SP(SS為堆棧段的段基址)
6、堆棧的生長方式
• 向上生長:當壓入操作后,堆棧指示器SP向地址增大方向變化。
• 向下生長:當壓入操作后,堆棧指示器SP向地址減小方向變化。
絕大多數計算機采用向下生長方式。
7、空棧:
在進行堆棧操作前,為空棧。此時SP應預置一個初值。該值為堆棧空間的大小。
SP初值=堆棧空間的最大容量例:SP=0008H。則最大容量為8個字節。SP指向當前的棧頂。