有些时候我们需要函数返回一个字符串但是总不能定义一个字符串函数吧?所以,这里介绍几种方法让函数返回字符串。
方法一:全局变量
全局变量是最简单的方法,如例子:
#include <stdio.h>
char chName[20];
void DoName()//使用全局变量的话就不必要设定函数类型了
{
//对chName的操作
...
return;
}
int main()
{
DoName();//执行对chName的操作
puts(chName);//输出chName的值
}
这种做法虽然函数不返回任何东西,但是作用是一样的。
注意:不推荐使用太多全局变量
方法2:指针和malloc动态分配空间
PS:关于malloc的用法介绍
如果不使用全局变量,我们同样可以定义一个指针类型的函数:
char *DoName()
然后返回一个指针(假设在函数中定义char *chName):
return chName;
但是并不是这么简单,因为函数所定义的变量在函数结束时就清空了,函数里的变量在函数外面不能用。函数定义的变量存储在系统中的栈里,当函数没有运行时,栈是这样的:
栈 |
栈顶-> 程序的其它信息… |
开始调用函数时:
栈 |
栈顶-> char *DoName |
程序的其它信息… |
执行到char *chName:
栈 |
栈顶-> char *chName |
… |
char *DoName |
程序的其它信息… |
当函数结束时:
栈 |
|
|
|
栈顶-> 程序的其它信息… |
此时,函数已经结束,函数定义的变量都从弹出了,没有了。而这时要是返回一个指针:
return chName;
要知道,指针,就是指向空间中的某个区域,而不是自身有值,如果函数结束了,返回一个指针,指针仍然指向函数那块已经清空的区域,那么就相当于返回的是空。如:
栈【函数运行中】 |
栈顶-> 指针指向-> char *chName |
… |
char *DoName |
程序的其它信息… |
栈【函数结束,函数定义的变量已经清空】 |
指针指向-> |
|
|
栈顶-> 程序的其它信息… |
那么这时,返回这个指针指向的区域,一块空的空间,那就没有起到作用。
那么,如何解决呢?
有请主角malloc出场!!
可以用malloc给*chName专门申请一块空间
chName = (char*)malloc(20);//给chName申请20的空间,相当于char chName[20]
那有人可能会问了,那这不还是一样的吗?
这可不一样,一般在函数中定义的变量在函数结束后在别的地方就用不了了,值被清空了。但是,用malloc申请的空间,不像函数一样,放在栈里,而是放在一个堆里,需要free才能清空。如:
- 函数未运行
栈 | 堆 |
栈顶-> 程序的其它信息… |
- 函数开始运行
栈 | 堆 |
栈顶-> char *DoName | |
程序的其它信息… |
- 函数运行中
栈 | 堆 |
栈顶-> chName = (char*)malloc(20) | |
char *chName | |
… | |
char *DoName | |
程序的其它信息… |
- 函数创建好了变量chName且申请过了空间,申请的空间在堆里。
栈 | 堆 |
栈顶-> … | |
chName = (char*)malloc(20) | |
char *chName | |
… | |
char *DoName | |
程序的其它信息… | 指针指向-> …(一些值) |
- 函数结束了,函数创建的变量都清空了,但是堆需要free来清空,但是没有使用free(),堆没有清空。
栈 | 堆 |
| |
| |
| |
| |
| |
栈顶-> 程序的其它信息… | 指针指向-> …(一些值) |
这时,函数返回了指针*chName,它指向堆中的某个区域,而不是已经清空的栈。主函数接收到这个指针,成功地从堆中得到了值:
char *DoName()
{
...
char *chName;
chName = (char*)malloc(20);
...
return chName;
}
int main()
{
char getName[20] = DoName();
puts(getName);
return 0;
}
这样就可以了。
错误的做法
注意了: 有人会觉得我返回一个字符串不就好了吗,干嘛像方法2这么麻烦呢?
错误的代码:
char *DoName()
{
char chName[4] = {'D','a','v','\0'};
return chName;
}
int main()
{
char getName[4] = DoName();
puts(getName);
return 0;
}
这样,貌似……也能得到值“Dav”啊("\0"是在字符串中表示字符串结束的符号)。
其实,这只是恰好程序没有别的要处理,没有清空栈罢了!现在可以得到,但在别的地方不一定能得到。如果你让程序处理一些东西的话,就得不到值了,所以,不要使用这种错误的做法。