C語言,C語言返回局部變量的幾種用法--(經典例子)


 寫在前面  

  一般來說,函數是可以返回局部變量的。 局部變量的作用域只在函數內部,在函數返回后,局部變量的內存已經釋放了。因此,如果函數返回的是局部變量的值,不涉及地址,程序不會出錯。但是如果返回的是局部變量的地址(指針)的話,程序運行后會出錯。

因為函數只是把指針復制后返回了,但是指針指向的內容已經被釋放了,這樣指針指向的內容就是不可預料的內容,調用就會出錯。准確來說,函數不能通過返回指向棧內存的指針(注意這里指的是棧,返回指向堆內存的指針是可以的)

  總結如下: 

  (1)返回指向字符串常量的指針

  (2)不能返回以局部變量方式創建的字符串數組首地址

  (3)在函數中,允許返回局部變量的值,不允許返回局部變量的地址

  (4)在函數中,如果函數的返回值非要是一個局部變量的地址,那么該局部變量一定要申明為static類型。

  (5)數組是不能作為函數的返回值

  (6)返回指向堆內存的指針是可以的

下面以函數返回局部變量的指針舉幾個典型的例子來說明:

1:返回指向字符串常量的指針

#include <stdio.h>
char *returnStr()
{
    char *p="hello world!";
    return p;
}
int main()
{
    char *str;
    str=returnStr();
    printf("%s\n", str);
    return 0;
}

        這個沒有任何問題,因為"hello world!"是一個字符串常量,存放在只讀數據段,把該字符串常量存放的只讀數據段的首地址賦值給了指針,所以returnStr函數退出時,該該字符串常量所在內存不會被回收,故能夠通過指針順利無誤的訪問。
 

2:不能返回以局部變量方式創建的字符串數組首地址

#include <stdio.h>
char *returnStr()
{
  char p[]="hello world!";
  return p;
}
int main()
{
  char *str;
  str=returnStr();
  printf("%s\n", str);
  return 0;
}

 

#include <stdio.h> char *returnStr() { char p[]="hello world!"; return p; } int main() { char *str; str=returnStr(); printf("%s\n", str); return 0; } "hello world!"是局部變量存放在棧中。當returnStr函數退出時,棧要清空,局部變量的內存也被清空了,所以這時的函數返回的是一個已被釋放的內存地址,所以有可能打印出來的是亂碼。

 

3:在函數中,允許返回局部變量的值,不允許返回局部變量的地址

int func()
{
  int a;
  ....
  return a; //允許
}
int * func()
{
  int a;
  ....
  return &a; //無意義,不應該這樣做
}
int func(){ int a; .... return a; //允許} int * func(){ int a; .... return &a; //無意義,不應該這樣做}

 

        局部變量也分局部自動變量和局部靜態變量,由於a返回的是值,因此返回一個局部變量是可以的,無論自動還是靜態,因為這時候返回的是這個局部變量的值,但不應該返回指向局部自動變量的指針,因為函數調用結束后該局部自動變量被拋棄,這個指針指向一個不再存在的對象,是無意義的。但可以返回指向局部靜態變量的指針,因為靜態變量的生存期從定義起到程序結束。

4:如果函數的返回值非要是一個局部變量的地址,那么該局部變量一定要申明為static類型。如下:

#include <stdio.h>
char *returnStr()
{
  static char p[]="hello world!";
  return p;
}
int main()
{
  char *str;
  str=returnStr();
  printf("%s\n", str);
  return 0;
}
#include <stdio.h> char *returnStr() { static char p[]="hello world!"; return p; } int main() { char *str; str=returnStr(); printf("%s\n", str); return 0; }

 

5: 數組是不能作為函數的返回值的,原因是編譯器把數組名認為是局部變量(數組)的地址。返回一個數組一般用返回指向這個數組的指針代替,而且這個指針不能指向一個自動數組,因為函數結束后自動數組被拋棄,但可以返回一個指向靜態局部數組的指針,因為靜態存儲期是從對象定義到程序結束的。如下:

int* func( void )
{
  static int a[10];
  ........
  return a;
}
int* func( void ){ static int a[10]; ........ return a;}
 

6:返回指向堆內存的指針是可以的

char *GetMemory3(int num)
{
  char *p = (char *)malloc(sizeof(char) * num);
  return p;
}
void Test3(void)
{
  char *str = NULL;
  str = GetMemory3(100);
  strcpy(str, "hello");
  cout<<str<<endl;
  free(str);
}
char *GetMemory3(int num){char *p = (char *)malloc(sizeof(char) * num);return p;}void Test3(void){char *str = NULL;str = GetMemory3(100);strcpy(str, "hello");cout<< str << endl;free(str);}

  程序在運行的時候用 malloc 申請任意多少的內存,程序員自己負責在何時用 free釋放內存。動態內存的生存期由程序員自己決定,使用非常靈活。

 

原文鏈接:https://blog.csdn.net/haiwil/article/details/6691854

 


免責聲明!

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



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