C語言 堆與棧
通過內(nèi)存組織方式可以看到,堆用來存放動態(tài)分配內(nèi)存空間,而棧用來存放局部數(shù)據(jù)對象、函數(shù)的參數(shù)以及調(diào)用函數(shù)和被調(diào)用函數(shù)的聯(lián)系,下面對二者進(jìn)行詳細(xì)的說明。
1.堆
在內(nèi)存的全局存儲空間中,用于程序動態(tài)分配和釋放的內(nèi)存塊稱為自由存儲空間,通常也稱之為堆。
在C程序中,是用malloc()和free()函數(shù)從堆中動態(tài)地分配和釋放內(nèi)存。
【例題】在堆中分配內(nèi)存并釋放
程序如下:
#include<studio.h>
int main()
{
int *plnt; /*定義整型指針*/
pInt=(int*)malloc(sizeof(int)); /*分配內(nèi)存*/
*plnt=100; /*使用分配內(nèi)存*/
printf("the number is: %d\n", pint); /*輸出顯示數(shù)值*/
return 0; /*釋放內(nèi)存*/
}
本程序中用malloc()函數(shù)分配一個整型變量的內(nèi)存空間,在使用完該空間后,使用free()函數(shù)釋放。
2.棧
在函數(shù)調(diào)用時,第一個進(jìn)棧的是主函數(shù)中函數(shù)調(diào)用后的下一條指令(函數(shù)調(diào)用語句的下一條可執(zhí)行語句)的地址,然后是函數(shù)的各個參數(shù)。在大多數(shù)的C編譯器中,參數(shù)是由右往左入棧的,然后是函數(shù)中的局部變量。注意靜態(tài)變量是不入棧的。
當(dāng)本次函數(shù)調(diào)用結(jié)束后,局部變量先出棧,然后是參數(shù),最后棧頂指針指向最開始存的地址,也就是主函數(shù)中的下一條指令,程序由該點繼續(xù)運行。
棧是一個后進(jìn)先出的壓入彈出式的數(shù)據(jù)結(jié)構(gòu)。在程序運行時,需要每次向棧中壓入一個對象,然后棧指針向下移動一個位置。當(dāng)系統(tǒng)從棧中彈出一個對象時,最晚進(jìn)棧的對象將被彈出,然后棧指針向上移動一個位置。如果棧指針位于棧頂,則表示棧是空的;如果棧指針指向最下面的數(shù)據(jù)項的后一個位置,則表示棧為滿的。其過程如圖所示。
程序員通常會利用棧這種數(shù)據(jù)結(jié)構(gòu)來處理那些最適用后進(jìn)先出邏輯描述的編程問題。這里討論的棧在程序中都會存在,它不需要程序員編寫代碼去維護(hù),而是運行時由系統(tǒng)自動處理。所謂的運行時系統(tǒng)維護(hù),實際上就是編譯器所產(chǎn)生的程序代碼。盡管在源代碼中看不到它們,但程序員應(yīng)該對此有所了解。這個特性和后進(jìn)先出的特性是棧明顯區(qū)別于堆的標(biāo)志。
棧是如何工作的呢?例如,當(dāng)一個函數(shù)A調(diào)用另一個函數(shù)B時,系統(tǒng)將會把函數(shù)A的所有實參和返回地址壓入到棧中,棧指針將移動到合適的位置來容納這些數(shù)據(jù)。最后進(jìn)棧的是函數(shù)A的返回地址。
當(dāng)函數(shù)B開始執(zhí)行后,系統(tǒng)把函數(shù)B的自變量壓入到棧中,并把棧指針再向下移,以保證有足夠的空間來存儲函數(shù)B聲明的所有自變量。
當(dāng)函數(shù)A的實參壓入棧后,函數(shù)B就在棧中以自變量的形式建立了形參。函數(shù)B內(nèi)部的其他自變量 也是存放在棧中的。由于這些進(jìn)棧操作,棧指針已經(jīng)壓到所有局部變量之下。但是函數(shù)B記錄了剛開始執(zhí)行時的初始棧指針,以這個指針為參考,用正偏移量或負(fù)偏移量來訪問棧中的變量。
當(dāng)函數(shù)B正準(zhǔn)備返回時,系統(tǒng)彈出棧中的所有自變量,這時棧指針移到了函數(shù)B剛開始執(zhí)行時的位置。接著,函數(shù)B返回,系統(tǒng)從棧中彈出返回地址,函數(shù)A就可以繼續(xù)執(zhí)行了。
當(dāng)函數(shù)A繼續(xù)執(zhí)行時,系統(tǒng)還能從棧中彈出調(diào)用者的實參,于是棧指針又回到了調(diào)用前的位置。
點擊加載更多評論>>