一般的來說,函數是可以傳回局部變量的。 局部變量的作用域隻在函數内部,在函數傳回後,局部變量的記憶體已經釋放了。是以,如果函數傳回的是局部變量的值,不涉及位址,程式不會出錯。但是如果傳回的是局部變量的位址(指針)的話,程式運作後會出錯。因為函數隻是把指針複制後傳回了,但是指針指向的内容已經被釋放了,這樣指針指向的内容就是不可預料的内容,調用就會出錯。準确的來說,函數不能通過傳回指向棧記憶體的指針(注意這裡指的是棧,傳回指向堆記憶體的指針是可以的)。
下面以函數傳回局部變量的指針舉幾個典型的例子來說明:
#include <stdio.h>
char *returnStr()
{
char *p="hello world!";
return p;
}
int main()
{
char *str;
str=returnStr();
printf("%s\n", str);
return ;
}
這個沒有任何問題,因為”hello world!”是一個字元串常量,存放在隻讀資料段,把該字元串常量存放的隻讀資料段的首位址指派給了指針,是以returnStr函數退出時,該該字元串常量所在記憶體不會被回收,故能夠通過指針順利無誤的通路。
#include <stdio.h>
char *returnStr()
{
char p[]="hello world!";
return p;
}
int main()
{
char *str;
str=returnStr();
printf("%s\n", str);
return ;
}
“hello world!”是局部變量存放在棧中。當returnStr函數退出時,棧要清空,局部變量的記憶體也被清空了,是以這時的函數傳回的是一個已被釋放的記憶體位址,是以有可能列印出來的是亂碼。
3:
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 ;
}
5: 數組是不能作為函數的傳回值的,原因是編譯器把數組名認為是局部變量(數組)的位址。傳回一個數組一般用傳回指向這個數組的指針代替,而且這個指針不能指向一個自動數組,因為函數結束後自動數組被抛棄,但可以傳回一個指向靜态局部數組的指針,因為靜态存儲期是從對象定義到程式結束的。如下:
int* func( void )
{
static int a[];
........
return a;
}
6:傳回指向堆記憶體的指針是可以的
char *GetMemory3(int num)
{
char *p = (char *)malloc(sizeof(char) * num);
return p;
}
void Test3(void)
{
char *str = NULL;
str = GetMemory3();
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
程式在運作的時候用 malloc 申請任意多少的記憶體,程式員自己負責在何時用 free釋放記憶體。動态記憶體的生存期由程式員自己決定,使用非常靈活。