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