函數返回局部變量/局部指針


c語言 返回局部變量 局部指針 局部數組

內存四區模型

  討論這個問題之前,一定要理解堆區和棧區的工作原理,數據的存儲區域(參考內存四區模型),另外一定不要返回局部對象或變量的引用和指針。

局部變量

  局部變量分局部自動變量和局部靜態變量,由於c返回的是值,因此返回一個局部變量是可以的,無論自動還是靜態,因為這時候返回的是這個局部變量的值。另外,函數返回局部變量時實際上是返回變量值的拷貝。a為局部變量,在棧區存儲,雖然在函數調用結束后所在內存會被釋放回收掉,但返回值不是訪問地址,而是a的拷貝副本。

1 int INTtest(){
2     int a = 10;
3     return a;
4 }

局部指針

  局部指針跟上面所述的局部變量一樣。可以返回一個局部指針的值,也可以返回一個局部靜態指針的地址,但不應該返回一個局部自動指針的地址,除非自動指針的地址指向數據區或堆區

  返回值為局部指針,可以分為:(1)聲明局部變量,返回其地址;(2)聲明局部數組,返回數組名;(3)聲明局部指針,返回該指針。

  1.返回局部變量地址,局部變量分為自動和靜態局部變量,不應該返回指向局部自動變量的指針,因為函數調用結束后棧上聲明的局部自動變量被拋棄,這個指針指向一個不再存在的對象,是無意義的。但可以返回指向局部靜態變量的指針,因為靜態變量存在數據區,它的生存期從定義起到程序結束。

  2.返回數組名,與局部變量相同(自動和靜態),調用的結果指向棧上聲明的數組的首地址,函數結束后自動數組內存釋放掉,將無法對其進行訪問(某些編譯器Release下可以訪問,但理論上是沒有意義的),但靜態數組可以。

  3.返回指針,調用結果指向該指針指向的內存,在函數結束后在棧上聲明的指針也會被釋放掉,但應該注意原指針指向的內存地址,若改地址同樣是棧上聲明的,則無法訪問,如果是數據區或堆區的內容,則可以訪問。

  1和2比較容易理解,這里不再進行舉例,僅對第3種情況的數據區和堆區進行說明。

  數據區:返回指針,但指針指向的內存地址存儲在數據區(常量區)

 1 char * test(){
 2     char *arr = "hello world"; //字符常量
 3     //static char arr[] = "hello world!";
 4     return arr;
 5 }
 6 
 7 void  test_(){
 8     char *s = test();
 9     printf("s = %s\n", s);
10 }
11 
12 int main(){
13     test_();
14         return 0;      
15 }

  堆區:返回指針,指針指向的內存地址存儲在堆區,沒有手動釋放前都可以訪問到。

 1 char *getstring(){
 2     char *p;
 3     p = malloc(100);
 4     memset(p, 0, 100);
 5     strcpy(p, "hello");
 6 
 7     return  p;
 8 }
 9 
10 void test(){
11     char *ret = getstring();
12     printf("%s\n", ret);
13     free(ret);
14     ret = NULL;
15 }
16 
17 int main(){
18 
19     test();
20 
21     system("pause");
22     return 0;
23 }

  如果指針指向的內存是在函數內部申請的,基本不干返回指針這種事,做這種事情很有可能是在給自己找麻煩,多數做的都是在可以釋放的地方申請好內存,通過指針傳遞進函數,申請和釋放都在同一函數中。上面的函數,可以修改如下:

 1 void getstring01(char *p){
 2     strcpy(p, "hello");
 3 }
 4 
 5 void test01(){
 6     char *p = NULL;
 7     p = malloc(100);
 8     memset(p, 0, 100);
 9     //char *ret = NULL;
10     getstring01(p);
11     printf("%s\n", p);
12     free(p);
13     p = NULL;
14 }
15 
16 
17 int main(){
18         test01();
19         return 0;
20 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM