C語(yǔ)言深入講解之從函數(shù)棧幀角度理解return關(guān)鍵字
初識(shí)函數(shù)棧幀

如上圖可見(jiàn),函數(shù)在被調(diào)用的時(shí)候會(huì)現(xiàn)在棧上開(kāi)辟一個(gè)空間,我們稱之為棧幀,之后函數(shù)內(nèi)部的變量在這塊區(qū)域進(jìn)行空間開(kāi)辟。
但是函數(shù)在調(diào)用的時(shí)候,怎么知道需要開(kāi)辟多大空間呢???
void func()
{
int a, b;
double c, d, e;
}
按照示例代碼,會(huì)先對(duì)需要的內(nèi)存空間大小進(jìn)行預(yù)估,然后進(jìn)行空間開(kāi)辟。
函數(shù)返回時(shí),棧幀會(huì)被釋放,但是,雖然棧幀被釋放,里面的內(nèi)容是不會(huì)被清空的,下面通過(guò)以下的例子進(jìn)行分析。
#include <stdio.h>
#include <windows>
char* show()
{
char str[] = "hello world!";
return str;
}
int main()
{
char* s = show();
printf("%s\n", s);
system("pause");
return 0;
}
運(yùn)行會(huì)得到亂碼的結(jié)果

看到這里,有些小伙伴肯定會(huì)說(shuō),嗷,return語(yǔ)句是不可以返回指向棧內(nèi)存的指針的。
可是這又是為什么呢?
于是我按下F11進(jìn)行調(diào)試。發(fā)現(xiàn)當(dāng)代碼進(jìn)行到printf語(yǔ)句行的時(shí)候,s指向的內(nèi)容依舊是hello world!。繼續(xù)F10,到14行的時(shí)候,printf函數(shù)被調(diào)用,s字符串居然又不存在了?。。?!
其實(shí),printf也是個(gè)函數(shù),也會(huì)在調(diào)用函數(shù)的時(shí)候形成棧幀,會(huì)覆蓋曾經(jīng)show棧幀存在的位置,而show棧幀在被釋放之后是無(wú)效的。
return
接下來(lái),讓我們把關(guān)注點(diǎn)放到return關(guān)鍵字,同樣的,從代碼出發(fā)~~

誒,那就奇怪了???上面不是說(shuō)過(guò)函數(shù)棧幀會(huì)被釋放嗎,那x的值又是怎么被y拿到的呀???
函數(shù)的返回值其實(shí)是通過(guò)寄存器的方式返回給調(diào)用方的
同樣的,讓我們看看調(diào)試。

這是進(jìn)入了GetData函數(shù)的匯編語(yǔ)言,eax其實(shí)就是寄存器,14行下一行的意思就是把x的內(nèi)容放入寄存器里。
然后我們繼續(xù)F11

回到了main函數(shù),發(fā)現(xiàn)eax會(huì)把值再次放入y中。
看到這里是不是恍然大悟了呢?。?!
來(lái)看另外一種情況,如果返回的值不被接收呢???

如果返回的值不被接收,GetData后續(xù)沒(méi)有處理eax。
個(gè)人總結(jié)環(huán)節(jié)
最后,來(lái)把知識(shí)點(diǎn)系統(tǒng)回顧一遍!
return返回值本質(zhì)上是通過(guò)寄存器返回的,如果返回的是一個(gè)值,在有變量接收該返回類型的情況下,可以打印該數(shù)據(jù)。如果返回的是一個(gè)指針,雖然可以接收到返回的地址,但是原來(lái)函數(shù)棧幀存在的位置會(huì)被覆蓋,指針?biāo)赶虻膬?nèi)容會(huì)在此時(shí)被改變。所以說(shuō),return語(yǔ)句不可以返回指向棧內(nèi)存的指針,該函數(shù)棧幀在結(jié)束時(shí)即被銷毀。
到此這篇關(guān)于C語(yǔ)言從函數(shù)棧幀角度理解return關(guān)鍵字的文章就介紹到這了,更多相關(guān)C語(yǔ)言之return關(guān)鍵字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言示例講解動(dòng)態(tài)/文件/靜態(tài)功能版本的通訊錄實(shí)現(xiàn)
通訊錄是一個(gè)可以記錄親人、好友信息的工具,這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)通訊錄管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
C++有限狀態(tài)機(jī)實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了C++有限狀態(tài)機(jī)的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
詳解Dev C++使用教程(使用Dev C++編寫(xiě)C語(yǔ)言程序)
這篇文章主要介紹了詳解Dev C++使用教程(使用Dev C++編寫(xiě)C語(yǔ)言程序),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
C語(yǔ)言實(shí)現(xiàn)輸出平均成績(jī)最高學(xué)生的信息
這篇文章主要介紹利用C語(yǔ)言實(shí)現(xiàn)輸出平均成績(jī)最高學(xué)生的信息,文章舉例說(shuō)明并附有詳細(xì)代碼,需要的朋友可以參考一下2021-10-10
C++設(shè)置超時(shí)時(shí)間的簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了C++設(shè)置超時(shí)時(shí)間的簡(jiǎn)單實(shí)現(xiàn)方法,涉及系統(tǒng)函數(shù)setsockopt對(duì)套接口的操作,具有一定的實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10
C++編程使用findfirst和findnext查找及遍歷文件實(shí)現(xiàn)示例
這篇文章主要為大家介紹了C++編程如何使用findfirst和findnext查找及遍歷文件實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10
C++實(shí)現(xiàn)的一個(gè)可以寫(xiě)遞歸lambda的Y函數(shù)
這篇文章主要介紹了C++實(shí)現(xiàn)的一個(gè)可以寫(xiě)遞歸lambda的Y函數(shù),在Y函數(shù)的幫助,這個(gè)lambda表達(dá)是可以成功看到自己,然后遞歸調(diào)用的,需要的朋友可以參考下2014-07-07

