C语言中函数返回字符串的4中方法
- 函数的构成部分:返回类型、函数名称、参数、函数主体
- 参数:函数调用时传入的参数称为实参,函数定义时出现的参数为形参
- 形参的作用在于接收实参传入的值,形参和函数内部的其他局部变量相同,在进入函数创建,退出函数销毁
- 值传递:实参的实际值复制给形式参数。修改形参不会改变实际参数
- 引用传递:指针传递,将实参地址复制给形参,修改形参指向的值时,实参也会发生改变
- 由此,可以得知无论是形式结合还是return语句返回时,都存在一个拷贝的过程。值传递的过程是将这个值拷贝一份在函数内部使用,引用传递的过程是将地址拷贝一份使用。同样在return返回时,返回一个值,函数会将该值拷贝一份供主函数使用,返回指针,自然拷贝的就是一个地址,供主函数使用。
- 下面是一个错误示例
#include <stdio.h>
#include <string.h> char * retstring();
int main()
{
char * name2;
name2 = retstring();
printf("%s\n",name2);
return 0;
} char * retstring()
{
char name[10];
strcpy(name,"汉青");
return name;
}- 上面这段代码会出现一个警告,这是因为返回了一个局部变量name的地址。在主函数中该局部变量name时处于销毁状态,所以name内存空间还没有被重写的话主函数中name2的值是正确,如果被其他程序重写,就会出现未知异常。
- 所以返回局部变量的字符串时很可怕的
- 函数返回字符串的方法:
- 将字符串指针作为函数参数传入,并返回该指针
- 使用malloc函数动态分配内存,在主调函数中释放
- 返回一个静态局部变量
- 使用全局变量
将字符串指针作为函数参数传入,并返回
- 典型的strcpy函数应该采用的就是这种方法:
char* strcpy(char* des,const char* source)
{
char* r=des;
assert((des != NULL) && (source != NULL));
while((*r++ = *source++)!='\0');
return des;
}
使用malloc函数动态分配内存,但是一定要注意在主调函数中将其释放,因为malloc动态分配的内存位于堆区,而堆区的内存是需要自己释放的###
#include <stdio.h>
#include <string.h>
#include <stdlib.h> char * retstring();
int main()
{
char * name2;
name2 = retstring();
printf("%s\n",name2);
//记住一定要用free释放,否则会造成内存泄露
free(name2);
return 0;
} char * retstring()
{
char * name;
name = (char *)malloc(10);
strcpy(name,"张汉青");
return name;
}
返回一个静态局部变量
#include <stdio.h>
#include <string.h>
#include <stdlib.h> char * retstring();
int main()
{
char * name2;
name2 = retstring();
printf("%s\n",name2);
return 0;
} char * retstring()
{
static char name[10];
strcpy(name,"张汉青");
return name;
}- 这种方法在于采用了静态局部变量(位于静态区,程序结束时由系统释放),这会导致,下一次调用会将上次调用产生的结构进行覆盖。
- 使用这样的函数应该立即将结构拷贝一份
使用全局变量
char g_s[100];
char* fun()
{
strcpy(g_s, "abc ");
return g_s;
}
函数返回字符串问题
- 归根结底,返回字符串就是要返回一个地址,同时需要保证地址在主调函数有效。
- 直接定义char*变量,会保存在栈区,变量的作用域外会被立即销毁;malloc申请空间保存在堆区,需要手动销毁;静态区变量程序结束时销毁。
- 所以返回一个地址要么扩大他的作用域,要么控制其生命周期。
- 引用自:https://www.cnblogs.com/qingergege/p/6496683.html