一:背景
談到C語言的函數返回值,可能會感覺很親切,不就是一個函數返回值嘛,當初學C語言的時候早就學過了很easy嘛,我曾經也是這麼想的。後來要上研究生了,研究生階段搞得就是C,所以又重新開始學習C,學習C的過程中遇到了很多問題,在此博客中一一記錄。實際過程中遇到的第一個問題自然就是函數返回值了。如果有人問你在一個函數中聲明一個字符串數組,最後再return這個數組。這可以實現嘛?如果是問我我可能會毫不猶豫的說OK。那事實呢?由此本文誕生了......
C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm
讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm
讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm
讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm
將C語言梳理一下,分布在以下10個章節中:
二:問題
先看幾個實際的例子:
#include<stdio.h>
#include<stdlib.h>
char *return_arry();
int main ( int argc, char *argv[] )
{
printf("%s\n",return_arry());
printf("%d\n",return_var());
return EXIT_SUCCESS;
}
/* ---------- end of function main ---------- */
char* return_arry ( )
{
char str[]="zhangyifei";
return str;
}
/* ----- end of function return_arry ----- */
int return_var ( )
{
int a = 5;
return a;
}
/* ----- end of function return_var ----- */
linux 下gcc編譯報錯如下:
return.c: In function ‘return_arry’:
return.c:35:2: warning: function returns address of local variable [-Wreturn-local-addr]
return str;
^
可見函數中是無法返回一個局部變量數組的。那為何return_var中沒有報錯呢。
其原因在於return a 其本質是返回了a的值,而return str則是返回了這個數組的首地址。然後str是一個局部變量,函數結束後這個地址就會被釋放掉。所以gcc提示。對於這類問題,我們要明確函數返回的是什麼,如果是值的話沒有關系,如果是地址的話,要看是局部的還是全局的還是堆的。如果是局部的就不能返回。如果是全局的就沒有關系了,如果是堆的那麼請記住要記得釋放掉。
三:方法
那麼對於一個函數來說,我該怎麼返回一個字符串呢。
方法如下:
方法一:返回一個指向字符串指針的常量。
char *func{return "only works for simple strings"}
http://www.linuxidc.com/Linux/2014-07/104737.htm 參見這篇博文,常量是存放再代碼段的,整個程序的執行周期都在不會因為子函數的結束而釋放。
這是最簡單的解決方案,但是如果你需要對字符串處理那就無能為力了。
方法二:使用全局數組
char *func(){
my_global_array[i] = 'a';
return my_global_array;
}
這種方法也是很簡單易用的,但是大量創建這樣的全局字符串數組增加了程序的耦合性。並且任何人都可以修改這個全局數組,而且下一次函數調用也會覆蓋該數組的內容。
方法三:使用靜態數組
char * func(){
static char buffer[20];
return buffer;
}
http://www.linuxidc.com/Linux/2014-07/104737.htm 參見這篇博文,靜態變量是存放在數據段的也是整個程序執行周期都不釋放的。
這種方法比使用全局數組要好,可以防止任何人修改這個數組的內容,只有擁有該數組的指針函數才能修改這個靜態數組。但是函數下一次調用將覆蓋這個數組的內容。
方法四:顯示分配一些內存
char *func()
{
char *s = malloc(120);
return s;
}
http://www.linuxidc.com/Linux/2014-07/104737.htm 參見這篇博文mlloc分配的內存是放在堆段的,只有編程者自己手動通過free來釋放內存的。所以不會因為函數執行完畢就釋放其內存。
但是這種方法要求編程者謹記要自己手動釋放內存,這種寫法不太好,因為malloc和free不在同一個代碼塊中很容易忘記使用free.
方法五:也許是最好的解決方案
void func(char *result,int size)
{
strcpy(result,"test",size);
}
buffer = malloc(size);
func(buffer,size);
free(buffer);
這種方案只要malloc和free的使用在一個代碼塊中那麼內存管理就顯得輕松了。
四:總結
C語言真的很簡單,簡單到什麼都要自己做。