新聞中心
c語言如何將函數(shù)調(diào)用堆棧打印出來
可以直接用輸出在函數(shù)內(nèi)部調(diào)用時,把調(diào)用順序打印出來。
創(chuàng)新互聯(lián)長期為成百上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為卡若企業(yè)提供專業(yè)的網(wǎng)站設(shè)計制作、成都網(wǎng)站建設(shè),卡若網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
一、一個由C/C++編譯的程序占用的內(nèi)存分為以下幾個部分
1、棧區(qū)(stack)—?由編譯器自動分配釋放?,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
2、堆區(qū)(heap)?—?一般由程序員分配釋放,?若程序員不釋放,程序結(jié)束時可能由OS回收?。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表,呵呵。
3、全局區(qū)(靜態(tài)區(qū))(static)—,全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,?未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。?-?程序結(jié)束后有系統(tǒng)釋放
4、文字常量區(qū)?—常量字符串就是放在這里的。?程序結(jié)束后由系統(tǒng)釋放
5、程序代碼區(qū)—存放函數(shù)體的二進制代碼。
二、例程:
//main.cpp?
int?a?=?0;?全局初始化區(qū)?
char?*p1;?全局未初始化區(qū)?
main()?
{?
int?b;?棧?
char?s[]?=?"abc";?棧?
char?*p2;?棧?
char?*p3?=?"123456";?123456在常量區(qū),p3在棧上。?
static?int?c?=0;?全局(靜態(tài))初始化區(qū)?
p1?=?(char?*)malloc(10);?
p2?=?(char?*)malloc(20);?
分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。?
strcpy(p1,?"123456");?123456放在常量區(qū),編譯器可能會將它與p3所指向的"123456"優(yōu)化成一個地方。?
}
c語言怎么調(diào)用棧函數(shù)
給你個例子:
#include
//寫好加法,以便調(diào)用
int sum(int x1,int x2)
{
int x3=x1+x2;
return x3;
}
void main()
{
int a=0;
int b=0;
int c=0;
printf("請輸入兩個整數(shù)\n");
scanf("%d%d",a,b);
c=sum(a,b);//傳遞參數(shù)給sum()函數(shù),返回他們的和
printf("%d+%d的和是:%d\n",a,b,c);
}
總之:就是你把一種方法寫到單獨的塊,這里就是sum()函數(shù),執(zhí)行一個單一的功能,在main函數(shù)調(diào)用就是了!
C語言中,函數(shù)調(diào)用是通過棧實現(xiàn)的,怎樣理解這句話?
因為函數(shù)調(diào)用的時候,就要將關(guān)鍵的寄存器的值存入堆棧中,等到執(zhí)行完之后又從堆棧中取出數(shù)據(jù)
,計算機底層,有cs和ip的指令指針,指向哪里就執(zhí)行哪里的指令,但是函數(shù)調(diào)用會人為的把cs和ip改變, 從而改變了指令執(zhí)行的位置,自然去執(zhí)行調(diào)用的函數(shù)了,但是此時,還是要將關(guān)鍵的寄存器存入堆棧,比如cs,等到調(diào)用玩之后,就又從堆棧中取出關(guān)鍵的寄存器的值,cs,ip還有別的一些
尤其是遞歸函數(shù)
C語言棧的調(diào)用。
程序中,一個函數(shù)是一個過程,這個過程可以分為包括傳入?yún)?shù)、過程代碼、返回三部分構(gòu)成。由于一個函數(shù)過程需要用到內(nèi)部變量、臨時變量等,所以需要在進程空間的棧空間分配一段存儲片段來存儲函數(shù)過程中的這些參數(shù),該內(nèi)存片段即為棧幀。
棧幀的由來:
為一個函數(shù)的過程提供一個存儲函數(shù)局部變量,參數(shù),返回地址和其他臨時變量;
棧幀的周期:
進入函數(shù)~函數(shù)返回,該階段內(nèi)棧幀作為
不同的語言具體的實現(xiàn)方式略有不同,但是,總體上,fun(a,b);
局部變量:
包括函數(shù)傳入的形參和函數(shù)內(nèi)部定義的變量;
返回地址:
指令指針p指向call
fun,那么fun棧幀存儲的返回地址為p+1;現(xiàn)今的編譯器的一個約定是將返回地址存到一個固定的寄存器中,這樣比讀取棧幀(內(nèi)存)效率要高。
臨時變量:
主要為計算,運算過程中的中間臨時變量;
參數(shù)傳遞:
其一:如果fun中調(diào)用另一個函數(shù)k(a,b...n);那么,傳遞的參數(shù)是形參,按照現(xiàn)代編譯規(guī)定,前k個形參是通過寄存器傳遞,后n-k個形參通過棧幀的實參部分(棧幀的尾部)來傳遞;
其二:主要為在fun中要調(diào)用函數(shù)g(a,b),那么為g()函數(shù)傳出實參(形參是通過寄存器來傳遞的)是通過“傳出實參”區(qū)塊進行的,這么做主要是為了保證該實參能夠被內(nèi)層嵌套的函數(shù)訪問。比如,g函數(shù)由調(diào)用一個k(a地址)函數(shù),同樣需要用到a的地址,所以fun在傳遞參數(shù)時必須為實參(a)傳遞申請固定的內(nèi)存存儲空間(而非用寄存器)這樣k函數(shù)可以通過固定的內(nèi)存地址(fun的形參列表來獲取參數(shù)值)。這時的g的棧幀為fun棧幀的下一幀(相鄰的空間地址),即調(diào)用者和被調(diào)用者的棧幀是相連的;
保護的寄存器:
棧幀作為函數(shù)過程的一個臨時內(nèi)存存儲區(qū)塊,同時負(fù)責(zé)函數(shù)調(diào)用過程中寄存器值的保存和還原。即:假設(shè)fun函數(shù)目前占用了寄存器ri存儲一個臨時變量t,而此時調(diào)用了函數(shù)g(),在g()函數(shù)中可能需要用到寄存器ri做運算的臨時存儲,那么如何確保g()函數(shù)調(diào)用返回后,ri恢復(fù)到fun中t的原來值。這就需要在調(diào)用者或者被調(diào)用者中選擇其一來保存原有ri的值,即caller-save或者callee-save。
網(wǎng)頁名稱:C語言函數(shù)調(diào)用堆棧 c語言堆棧
新聞來源:http://ef60e0e.cn/article/dodcoch.html