關於c語言中堆、棧認識的彙總(參考論壇回帖)

pengfoo發表於2012-02-16

1.堆是是不連續的記憶體區域,棧是是一塊連續的記憶體的區域(有待考證)

2.為什麼c語言在執行工作時程式將使用一個執行時堆疊在中國一些老師或一些低劣質量的書,喜歡把棧叫堆疊。其實堆,棧是棧。c語言在執行工作時程式將使用一個執行時堆疊,其實C語言是基於過程的語言,又叫基於函式的語言。而函式的呼叫過程用棧又非常的合適。所以,伴隨程式的執行,函式的呼叫都預設給一個棧,基本上是一個執行緒就有一個呼叫棧。C++,C#,JAVA,都一個道理。

3.要在函式B裡面呼叫函式A應該怎麼做?是不是應該先將B的當前狀態儲存下來,然後再將A的資料裝進來,等A處理完了以後,再將A的資料清除,最後將B的狀態恢復...其實這個過程就是一個棧的結構,先將壓棧的順序是 B的狀態->A的資料,出棧順序相反 A的資料->B的狀態。這不就和上面的處理過程一致嗎?當然,你使用其他的方法也是可以的,但是棧的操作要簡單許多,壓棧和出棧只需要移動頭指標就可以了。

4.學過組合語言嗎?如果學過的話就很好解釋啦,不過也沒事,其實你問的問題是涉及到C的底層工作機制的,C的底層就是彙編,我們舉一個例子,pirntf("%d %d",a,b);這個函式的實現機制是什麼呢?首先這個函式有三個引數,在執行此函式時,會將此函式的三個引數壓入棧中(sp指標會一直指向棧頂元素的),那麼函式就會對這些資料進行處理(因為就在棧中,很容易找到資料的位置,這些不是你做的,是編譯器替你完成的),如果函式呼叫完成,則sp就會恢復到函式呼叫前的位置,也就是我們說的資料被釋放啦,其他函式也是如此。比如:
int add(int x,int y)
{
  int z;
  z = x + y;
  return z;
}

只是在棧中又開闢了z的空間,函式呼叫後會自動釋放的。這就是我們經常說的區域性變數,如果想深入理解他的彙編級是怎麼實現的,請用command下debug -u 進行反彙編,找到彙編程式碼仔細研究。堆就是函式動態分配的空間,比如malloc();分配的空間都是在堆裡面,我所講的都是在DOS下,windows下會稍微複雜一些,基本原理都一樣。

5.簡單點,為什麼需要棧? 棧是一種資料結構,無論是程式還是計算機內部,都大量地用到棧這種資料結構。如函式的呼叫,需要用棧來維護,這樣使得程式執行更容易維護,更加效率。堆,最大的特點就是在程式執行時可動態申請記憶體

6.LZ只的是呼叫棧吧,它是用來描述函式之間的呼叫關係的,呼叫棧有stack frame組成,每一個stack frame對應著一個為執行完的函式

7.堆 heap 棧 stack  堆疊這種說法是不嚴格的,儘量別用這種說法。
為什麼要用堆疊?這樣可以更好的利用記憶體空間。(之前的記憶體是非常的寶貴的) 棧可以幫助程式設計師管理一小部分的記憶體(區域性變數等退出函式後就銷燬了)。而堆即是供程式設計師支配管理的。這樣就很靈活了,又不會令程式設計師太累,又給程式設計師發揮的空間。而且兩者增長方向剛好相反,棧是從高地址到低地址,堆是從低地址到高地址。這樣空間利用的很充分。
8.C語言的區域性變數和引數傳遞都需要大量使用堆疊。在一個程式順序中,大函式呼叫小函式需要向棧壓入其所需要的引數,所以就要改變堆疊內容。多執行緒的程式執行期間不同的執行緒中其所使用的記憶體資料也不相同,如果還使用同一個棧的話,那麼引數勢必會發生混亂,如果使用靜態堆疊,那麼所有的程式碼都需要基於一個固定的地址來做堆疊操作,函式中想使用堆疊就全部需要按絕對地址定位,這樣非常非常不方便。
對於多執行緒來說,每一個執行緒都需要一個棧,所以堆疊是建立執行緒的時候動態分配的。單執行緒程式與多執行緒程式並沒有本質的區別,它們都是一個程式中包含1~N個執行緒的形式,所以單執行緒程式的堆疊也是在建立該程式的主執行緒時是為其主執行緒分配的。
程式中使用棧結構是因為它可以很方便地管理一個模組內所需要使用的記憶體。在堆疊平衡原則的約束下,一個順序執行中各個模組在執行的時候都擁有一個堆疊空間,當它執行完畢後只要將esp掉正回撥用它時的那個樣子那麼它對呼叫者就不會有任何破壞左右。程式呼叫的時候,因為執行完被呼叫的函式必須得將呼叫前的ip暫存器地址快取下來才可以恢復。這些必要的臨時資料都需要一個資料結構將它們儲存起來而且也需要快速方便地找到。對於這種需要,老外們研究出了這種棧結構。

因為保護模式下的windows是不允許使用野生記憶體的,所以程式在記憶體中除了檔案的對映以外其它所需要的記憶體都是以堆或棧的形式提供出來,所以堆疊就是程式中所有動態資料所使用的記憶體。堆和棧各是一種資料結構,也有人喜歡把棧叫做堆疊。

9.這個看linux核心原理就知道了,linux可執行的程式叫ELF格式,他規定了各個區域包括大家知道的 全域性變數區,BSS區,程式碼區,等等,當然了,堆的使用也linux作業系統也是相關的,在設計OS的時候,就考慮到程式需要動態獲得記憶體了。而棧個人感覺是C語言自己設計的,也就是說編譯器自己安排的。這個觀點可以見C專家程式設計,有一章講述這個問題的。

相關文章