谈到C语言的函数返回值,可能会感觉很亲切,不就是一个函数返回值嘛,当初学C语言的时候早就学过了很easy嘛,我曾经也是这么想的。后来要上研究生了,研究生阶段搞得就是C,所以又重新开始学习C,学习C的过程中遇到了很多问题,在此博客中一一记录。实际过程中遇到的第一个问题自然就是函数返回值了。如果有人问你在一个函数中声明一个字符串数组,最后再return这个数组。这可以实现嘛?如果是问我我可能会毫不犹豫的说OK。那事实呢?由此本文诞生了......
C++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码
将C语言梳理一下,分布在以下10个章节中:
Linux-C成长之路(十):其他高级议题
二:问题
先看几个实际的例子:
#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"}
参见这篇博文,常量是存放再代码段的,整个程序的执行周期都在不会因为子函数的结束而释放。
这是最简单的解决方案,但是如果你需要对字符串处理那就无能为力了。
方法二:使用全局数组
char *func(){
my_global_array[i] = 'a';
return my_global_array;
}
这种方法也是很简单易用的,但是大量创建这样的全局字符串数组增加了程序的耦合性。并且任何人都可以修改这个全局数组,而且下一次函数调用也会覆盖该数组的内容。
方法三:使用静态数组
char * func(){
static char buffer[20];
return buffer;
}
参见这篇博文,静态变量是存放在数据段的也是整个程序执行周期都不释放的。
这种方法比使用全局数组要好,可以防止任何人修改这个数组的内容,只有拥有该数组的指针函数才能修改这个静态数组。但是函数下一次调用将覆盖这个数组的内容。
方法四:显示分配一些内存
char *func()
{
char *s = malloc(120);
return s;
}