初識函數棧幀
如上圖可見,函數在被調用的時候會現在棧上開辟一個空間,我們稱之為棧幀,之后函數內部的變量在這塊區域進行空間開辟。
但是函數在調用的時候,怎么知道需要開辟多大空間呢???
void func() { int a, b; double c, d, e; }
按照示例代碼,會先對需要的內存空間大小進行預估,然后進行空間開辟。
函數返回時,棧幀會被釋放,但是,雖然棧幀被釋放,里面的內容是不會被清空的,下面通過以下的例子進行分析。
#include <stdio.h> #include <windows> char* show() { char str[] = "hello world!"; return str; } int main() { char* s = show(); printf("%s ", s); system("pause"); return 0; }
運行會得到亂碼的結果
看到這里,有些小伙伴肯定會說,嗷,return語句是不可以返回指向棧內存的指針的。
可是這又是為什么呢?
于是我按下F11進行調試。發現當代碼進行到printf
語句行的時候,s指向的內容依舊是hello world!
。繼續F10,到14行的時候,printf函數被調用,s字符串居然又不存在了!!!!
其實,printf也是個函數,也會在調用函數的時候形成棧幀,會覆蓋曾經show棧幀存在的位置,而show棧幀在被釋放之后是無效的。
return
接下來,讓我們把關注點放到return關鍵字,同樣的,從代碼出發~~
誒,那就奇怪了???上面不是說過函數棧幀會被釋放嗎,那x的值又是怎么被y拿到的呀???
函數的返回值其實是通過寄存器的方式返回給調用方的
同樣的,讓我們看看調試。
這是進入了GetData函數的匯編語言,eax其實就是寄存器,14行下一行的意思就是把x的內容放入寄存器里。
然后我們繼續F11
回到了main函數,發現eax會把值再次放入y中。
看到這里是不是恍然大悟了呢!!!
來看另外一種情況,如果返回的值不被接收呢???
如果返回的值不被接收,GetData后續沒有處理eax。
個人總結環節
最后,來把知識點系統回顧一遍!
return返回值本質上是通過寄存器返回的,如果返回的是一個值,在有變量接收該返回類型的情況下,可以打印該數據。如果返回的是一個指針,雖然可以接收到返回的地址,但是原來函數棧幀存在的位置會被覆蓋,指針所指向的內容會在此時被改變。所以說,return語句不可以返回指向棧內存的指針,該函數棧幀在結束時即被銷毀。
到此這篇關于C語言從函數棧幀角度理解return關鍵字的文章就介紹到這了,更多相關C語言之return關鍵字內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/Joy_Cheung666/article/details/120387700