C语言,函数不可返回指向栈内存的指针
預(yù)備知識:內(nèi)存的分類
C/C++程序占用的內(nèi)存分為兩大類:靜態(tài)存儲區(qū)與動態(tài)存儲區(qū)。其示意圖如下所示:
數(shù)據(jù)保存在靜態(tài)存儲區(qū)與動態(tài)存儲區(qū)的區(qū)別就是:靜態(tài)存儲區(qū)在編譯-鏈接階段已經(jīng)確定了,程序運行過程中不會變化,只有當(dāng)程序退出的時候,靜態(tài)存儲區(qū)的內(nèi)存才會被系統(tǒng)回收。動態(tài)存儲區(qū)是在程序運行過程中動態(tài)分配的。
在其它地方我們還可以看到內(nèi)存分配還有其他分類,那些都是細分的分類,比如文字常量區(qū)、全局數(shù)據(jù)區(qū)等,都歸為靜態(tài)存儲區(qū)這一個大類。
關(guān)于內(nèi)存的分類這里只是大致說一下,關(guān)于內(nèi)存更詳細的內(nèi)容可查看往期筆記:【C語言筆記】內(nèi)存總結(jié)
例子:return返回指向棧內(nèi)存指針
先看一個return返回指向棧內(nèi)存指針的例子:
#include?<stdio.h>char?*GetStr(void) {char?p[]?=?"Hello";?/*?保存在棧中?*/return?p; }int?main(void)? {char?*str?=?NULL;str?=?GetStr();printf("%s\n",?str);return?0; }程序編譯、運行的結(jié)果如下:
可以看到,編譯出現(xiàn)警告:
warning: function returns address of local variable
運行結(jié)果并不是我們期望的輸出字符串Hello。
那是因為GetStr函數(shù)返回指向棧內(nèi)存的指針,這里的變量p是局部變量,而局部變量是分配在棧上的。即Hello保存在棧內(nèi)存上,棧內(nèi)存在函數(shù)調(diào)用結(jié)束時會自動銷毀,因此此時的p里的內(nèi)容是未知的,所以結(jié)果無輸出。
下面我們把GetStr函數(shù)修改為:
char?*GetStr(void) {char?*p?=?"Hello";??/*?p在棧上,Hello在靜態(tài)區(qū)(常量區(qū))?*/return?p; }此時編譯運行的結(jié)果是怎樣的呢?結(jié)果為:
可以看到能正常輸出。為什么這里又可以正常輸出呢?因為這里的p雖然分配在棧上,但是此時的Hello是一個字符串常量,其存儲在靜態(tài)存儲區(qū)。在調(diào)用GetStr函數(shù)結(jié)束時其也不會被銷毀。
這里可能有些人會有疑惑,同樣是Hello,為什么一個在棧上,一個在靜態(tài)區(qū)。
char?*p?=?"Hello";此處首先定義了一個指針變量p,編譯器就會為指針變量開辟了棧空間。而此時并沒有空間來存放Hello,所以Hello只能存儲在靜態(tài)區(qū)。
char?p[]?=?"Hello";此處首先定義一個數(shù)組p,因為未給出數(shù)組大小,所以此時數(shù)組大小未確定。然后把Hello保存在這個數(shù)組里,編譯器就會為數(shù)組p開閉足夠的棧空間來存儲Hello。
相關(guān)筆記:char *str與char str[]的區(qū)別
其它替代方法
從上面的例子我們知道,若函數(shù)返回指向棧內(nèi)存的指針,所得到的結(jié)果并不是我們想要的。除了上面的方法之外,這里還有如下幾種解決方法:
1、把p定義為全局變量,因為全局變量存儲在靜態(tài)存儲區(qū),程序結(jié)束才會釋放。但是這樣會導(dǎo)致函數(shù)是不可重入的。關(guān)于函數(shù)的重入與不可重入可查看往期筆記:什么是可重入函數(shù)?
2、在GetStr函數(shù)中使用malloc申請動態(tài)內(nèi)存,但使用完一定要記得使用free進行釋放,否則會導(dǎo)致內(nèi)存泄漏。示例代碼如下:
#include?<stdio.h> #include?<stdlib.h> #include?<string.h>char?*GetStr(void) {char?*p?=?(char*)malloc(64*sizeof(char));strcpy(p,?"Hello");return?p; }int?main(void)? {char?*str?=?NULL;str?=?GetStr();printf("%s\n",?str);free(str);??/*?釋放str指向的堆內(nèi)存?*/return?0; }3、可以將變量p聲明為static靜態(tài)變量。但這也會導(dǎo)致函數(shù)是不可重入的。示例代碼如下:
char?*GetStr(void) {static?char?p[]?=?"Hello";return?p; }End:以上就是本次的筆記分享,如有錯誤,歡迎之處!如果這篇筆記對你有幫助的話,歡迎收藏、轉(zhuǎn)發(fā)、在看~
掃碼或長按關(guān)注
回復(fù)「?籃球的大肚子」進入技術(shù)群聊
總結(jié)
以上是生活随笔為你收集整理的C语言,函数不可返回指向栈内存的指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾讯电脑管家具有计算机病毒查杀功能,腾讯
- 下一篇: 美媒:软银售ARM中国子公司51%股权,