p是指向局部變量的指針,當(dāng)函數(shù)退出時(shí),局部變量會(huì)被釋放,這時(shí),p所指向的位置就不一樣是原來(lái)的數(shù)。

創(chuàng)新互聯(lián)公司是專(zhuān)業(yè)的西安網(wǎng)站建設(shè)公司,西安接單;提供成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行西安網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
因?yàn)閒un()函數(shù)返回的值被計(jì)算機(jī)的臨時(shí)變量存放,當(dāng)賦值給p的時(shí)候,p是指向臨時(shí)變量的地址,所以還可以讀取出100。
*p = "hello"這是常量字符串,從靜態(tài)存儲(chǔ)區(qū)分配,第一步字符串"hello"從靜態(tài)存儲(chǔ)區(qū)獲取一塊內(nèi)存,指針變量p才指向這塊靜態(tài)內(nèi)存,這塊內(nèi)存的特點(diǎn)是從程序開(kāi)始到結(jié)束一直從在,所以可以返回。
擴(kuò)展資料:
函數(shù)的返回值類(lèi)型是在定義函數(shù)時(shí)指定的。return 語(yǔ)句中表達(dá)式的類(lèi)型應(yīng)與定義函數(shù)時(shí)指定的返回值類(lèi)型一致。如果不一致,則以函數(shù)定義時(shí)的返回值類(lèi)型為準(zhǔn),對(duì) return 語(yǔ)句中表達(dá)式的類(lèi)型自動(dòng)進(jìn)行轉(zhuǎn)換,然后再將它返回給主調(diào)函數(shù)使用。
在調(diào)用函數(shù)時(shí),如果需要從被調(diào)函數(shù)返回一個(gè)值供主調(diào)函數(shù)使用,那么返回值類(lèi)型必須定義成非 void 型。此時(shí)被調(diào)函數(shù)中必須包含 return 語(yǔ)句,而且 return 后面必須要有返回值,否則就是語(yǔ)法錯(cuò)誤。
參考資料來(lái)源:百度百科-返回值
程序的執(zhí)行過(guò)程可看作連續(xù)的函數(shù)調(diào)用。當(dāng)一個(gè)函數(shù)執(zhí)行完畢時(shí),程序要回到調(diào)用指令的下一條指令(緊接call指令)處繼續(xù)執(zhí)行。函數(shù)調(diào)用過(guò)程通常使用堆棧實(shí)現(xiàn),每個(gè)用戶(hù)態(tài)進(jìn)程對(duì)應(yīng)一個(gè)調(diào)用棧結(jié)構(gòu)(call stack)。編譯器使用堆棧傳遞函數(shù)參數(shù)、保存返回地址、臨時(shí)保存寄存器原有值(即函數(shù)調(diào)用的上下文)以備恢復(fù)以及存儲(chǔ)本地局部變量。
不同處理器和編譯器的堆棧布局、函數(shù)調(diào)用方法都可能不同,但堆棧的基本概念是一樣的。
寄存器是處理器加工數(shù)據(jù)或運(yùn)行程序的重要載體,用于存放程序執(zhí)行中用到的數(shù)據(jù)和指令。因此函數(shù)調(diào)用棧的實(shí)現(xiàn)與處理器寄存器組密切相關(guān)。
AX(AH、AL):累加器。有些指令約定以AX(或AL)為源或目的寄存器。輸入/輸出指令必須通過(guò)AX或AL實(shí)現(xiàn),例如:端口地址為43H的內(nèi)容讀入CPU的指令為INAL,43H或INAX,43H。目的操作數(shù)只能是AL/AX,而不能是其他的寄存器。 [5]
BX(BH、BL): 基址寄存器 。BX可用作間接尋址的地址寄存器和 基地址寄存器 ,BH、BL可用作8位通用數(shù)據(jù)寄存器。 [5]
CX(CH、CL):計(jì)數(shù)寄存器。CX在循環(huán)和串操作中充當(dāng)計(jì)數(shù)器,指令執(zhí)行后CX內(nèi)容自動(dòng)修改,因此稱(chēng)為計(jì)數(shù)寄存器。 [5]
DX(DH、DL):數(shù)據(jù)寄存器。除用作通用寄存器外,在 I/O指令 中可用作端口 地址寄存器 ,乘除指令中用作輔助累加器。 [5]
2.指針和 變址寄存器
BP( Base Pointer Register):基址指針寄存器。 [5]
SP( Stack Pointer Register): 堆棧指針寄存器 。 [5]
SI( Source Index Register):源變址寄存器。 [5]
DI( Destination Index Register):目的變址寄存器。 [5]
函數(shù)調(diào)用棧的典型內(nèi)存布局如下圖所示:
圖中給出主調(diào)函數(shù)(caller)和被調(diào)函數(shù)(callee)的棧幀布局,"m(%ebp)"表示以EBP為基地址、偏移量為m字節(jié)的內(nèi)存空間(中的內(nèi)容)。該圖基于兩個(gè)假設(shè):第一,函數(shù)返回值不是結(jié)構(gòu)體或聯(lián)合體,否則第一個(gè)參數(shù)將位于"12(%ebp)" 處;第二,每個(gè)參數(shù)都是4字節(jié)大小(棧的粒度為4字節(jié))。在本文后續(xù)章節(jié)將就參數(shù)的傳遞和大小問(wèn)題做進(jìn)一步的探討。 此外,函數(shù)可以沒(méi)有參數(shù)和局部變量,故圖中“Argument(參數(shù))”和“Local Variable(局部變量)”不是函數(shù)棧幀結(jié)構(gòu)的必需部分。
其中,主調(diào)函數(shù)將參數(shù)按照調(diào)用約定依次入棧(圖中為從右到左),然后將指令指針EIP入棧以保存主調(diào)函數(shù)的返回地址(下一條待執(zhí)行指令的地址)。進(jìn)入被調(diào)函數(shù)時(shí),被調(diào)函數(shù)將主調(diào)函數(shù)的幀基指針EBP入棧,并將主調(diào)函數(shù)的棧頂指針ESP值賦給被調(diào)函數(shù)的EBP(作為被調(diào)函數(shù)的棧底),接著改變ESP值來(lái)為函數(shù)局部變量預(yù)留空間。此時(shí)被調(diào)函數(shù)幀基指針指向被調(diào)函數(shù)的棧底。以該地址為基準(zhǔn),向上(棧底方向)可獲取主調(diào)函數(shù)的返回地址、參數(shù)值,向下(棧頂方向)能獲取被調(diào)函數(shù)的局部變量值,而該地址處又存放著上一層主調(diào)函數(shù)的幀基指針值。本級(jí)調(diào)用結(jié)束后,將EBP指針值賦給ESP,使ESP再次指向被調(diào)函數(shù)棧底以釋放局部變量;再將已壓棧的主調(diào)函數(shù)幀基指針彈出到EBP,并彈出返回地址到EIP。ESP繼續(xù)上移越過(guò)參數(shù),最終回到函數(shù)調(diào)用前的狀態(tài),即恢復(fù)原來(lái)主調(diào)函數(shù)的棧幀。如此遞歸便形成函數(shù)調(diào)用棧。
EBP指針在當(dāng)前函數(shù)運(yùn)行過(guò)程中(未調(diào)用其他函數(shù)時(shí))保持不變。在函數(shù)調(diào)用前,ESP指針指向棧頂?shù)刂罚彩菞5椎刂贰T诤瘮?shù)完成現(xiàn)場(chǎng)保護(hù)之類(lèi)的初始化工作后,ESP會(huì)始終指向當(dāng)前函數(shù)棧幀的棧頂,此時(shí),若
#includestdio.h
#define stacksize 100 //假定預(yù)分配的棧空間最多為100 個(gè)元素
typedef char elementtype; //假定棧元素的數(shù)據(jù)類(lèi)型為字符 ,在此處可以自行設(shè)置
typedef struct
{
elementtype data[stacksize];
int top;
}seqstack;
// 置空棧
void initstack(seqstack *s)
{
s-top=-1;
//解釋一下,s-top 指向的是當(dāng)前棧頂元素的位置
//當(dāng)要向棧中添加一個(gè)新元素時(shí),要先將s-top增加1,
//此時(shí)s-top 指向的就是新元素要添加的位置了。
//所以當(dāng)棧為空時(shí),填加第一元素時(shí),top加1 后
//s-top的值就變?yōu)?,也就是第一個(gè)元素的位置了。
}
//判棧空
int stackempty(seqstack *s)
{
if(s-top==-1)
return 1; //若相等就返回1,否則為0
else return 0;
}
//入棧
void push(seqstack *s,elementtype x)
{
if(s-top==stacksize -1 ) //進(jìn)棧前判斷棧是否已經(jīng)滿(mǎn)了
printf(" stack overflow\n");
else
{
s-top= s-top + 1;
s-data[s-top]=x;
}
}
//出棧
elementtype pop(seqstack *s)
{
if(stackempty(s)) //出棧前先判斷當(dāng)前棧中是否有內(nèi)容
printf("stack is empty\n");
else
{
return s-data[s-top--]; //出棧后s-top的值會(huì)自減1
}
}
//取棧頂元素(只是想知道棧頂?shù)闹担](méi)有出棧)
elementtype gettop(seqstack *s)
{
if(stackempty(s))
{
printf("stack already empty.\n");
}
else return s-data[s-top];
}
int main()
{
elementtype x;
seqstack *s; //定義一個(gè)棧,用指針的方式定義的
initstack(s); //想初始化定義好的棧
//當(dāng)棧為空時(shí)調(diào)用出棧操作
pop(s);
//向棧中添加一個(gè)元素a
push(s,'a');
//觀察此時(shí)的棧頂元素
x=gettop(s);
printf("%c\n",x);
//再添加一個(gè)元素b
push(s,'b');
//觀察此時(shí)的棧頂元素
x=gettop(s);
printf("%c\n",x);
//彈出棧頂?shù)脑?/p>
x=pop(s);
printf("%c\n",x);
//觀察彈出后棧頂元素的變化情況
x=gettop(s);
printf("%c\n",x);
return 0;
}
必須出棧!
aa 和 bb 和c 都是函數(shù)內(nèi)部的局部變量,函數(shù)返回后就被釋放,也就是在棧中沒(méi)有了,返回后就剩下圖中main()函數(shù)所對(duì)應(yīng)的棧結(jié)構(gòu).
棧只能夠通過(guò)出棧來(lái)減少棧中數(shù)據(jù)的個(gè)數(shù),從反面來(lái)講,如果不出棧,funcA()函數(shù)返回后,棧指針還是指向c那,這肯定是不對(duì)的,因?yàn)楹瘮?shù)返回后棧指針就得指向man()的棧結(jié)構(gòu)了。
新聞標(biāo)題:c語(yǔ)言函數(shù)怎么返回一個(gè)棧,c語(yǔ)言返回某一步
網(wǎng)站地址:http://chinadenli.net/article32/dsepcpc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶(hù)體驗(yàn)、App設(shè)計(jì)、Google、定制開(kāi)發(fā)、軟件開(kāi)發(fā)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)