上次写了一篇在自定义函数中定义一个数组,再用一个指针来指向该数组的首地址,最后返回该指针给主函数里面的一个指针,最后在主函数里输出该指针的值,有时候存在很大的隐患。相对自顶函数中返回值的问题,做一些恰当的处理来防止返回值正常的输出。
解决方案
- 使用静态变量
下面的代码是我在做课程设计的时候,当时发现问题后,很慌张的赶紧把自己的代码做了一个相对比较妥当的处理。
static char name11[PATH_MAX]={0};
char *p = name11;//记录该用户下的学生成绩文件studet.txt
在这段代码中,也是返回指针p,可以看出指针p是在子函数里是指向name11的,但是当这个自定义函数结束的时候,自定义的数组name11这个变量是会释放的,,但是又有指针指向了它,返回的时候存在很大的不稳定因素。所以索性在这里将name11变成了静态变量。静态变量就是和程序有着相同周期的变量,我觉得可以规划为全局变量中。它只需要初始化一次,所以在此处采用静态变量感觉也很极端吧,毕竟如果后面发现开的空间不够用的时候,只能重新定义了,它全部过程只能被初始化一次,之后的值一直都是保持在程序操作之后。可以通过一个简单的程序来验证此特性。
#include<stdio.h>
int sum()
{
static int sum = 0;
sum = sum+1;
return sum;
}
int main()
{
int S = 0;
printf("sum1 = %d\n",S = sum());
printf("sum2 = %d\n",S = sum());
printf("sum3 = %d\n",S = sum());
printf("sum4 = %d\n",S = sum());
printf("sum5 = %d\n",S = sum());
printf("sum6 = %d\n",S = sum());
printf("sum7 = %d\n",S = sum());
}
通过结果可以看出只要在子函数里面把sum定义为静态变量之后,那么它只是遵循第一次的初始化,之后再也不经过sum = 0的初始化了。
通过这个小测试可以看出,在课程设计中的代码采用static变量的方式使用起来也不太方便,但是将它定义为静态变量可以防止在子函数结束的时候将那个局部数组变量释放,可以避免出现指针返回的时候出现内容区域没有程序使用权的情况。
2.使用动态储存方式
主要通过自己开辟空间,在堆上来建立变量,这样需要通过自己手动去开辟空间,最后也需要自己去释放那块空间。这一块主要要考虑在C语言上四个内存空间。堆区主要是要通过程序员自己分配的,需要自己申请与释放,如果不释放,最后由程序结束后,操作系统自己收回那块区域。所以解决自定义函数中返回值为指针,为了防止返回不正常的情况,可以通过自己定义动态数组来解决这种类型的问题。
- 首先来看不定义动态数组,直接返回的情况
char *fanhui()
{
//char *p = (char*)malloc(200);
char p[200];
char q[100]="李四/student.txt";
strcpy(p,q);
return p;
}
int main()
{
printf("p = %s\n",fanhui());
//free(p);
}
其中有一个提示,是警告提示,它明确的告诉你是不能返回p的,强行返回,最后生成可执行文件,运行出来p是一个空指针,是返回不了理想的结果的
- 使用动态数组来得到返回值
#include<string.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
char *fanhui()
{
char *p = (char*)malloc(200);
char q[100]="李四/student.txt";
strcpy(p,q);
return p;
}
int main()
{
printf("p = %s\n",fanhui());
}
从两次测试可以看出使用动态分配内存的方法就能够正常返回所需要的东西了。因为动态分配内存,是需要程序员自己开辟,最后自己free掉的。
3. 使用字符串常量(只是限制于返回值为字符型的指针)
字符串常量也是存在静态存储区,定义一个指针的时候,它是直接指向了字符串的地址。这样返回也是有不定因素的,它是局限于字符串的。
#include<string.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
char *fanhui()
{
char *p = "李四/student.txt";
return p;
}
int main()
{
printf("p = %s\n",fanhui());
}
- 使用const来限制(限制于返回类型是字符型指针)
使用const粗暴简单的限制了该变量不能被修改。只要用了const会防止任何修改,包括程序中的修改,编译的时候都会报错。
此处借用了static,改成了const.所以防止字符型指针返回的问题,也可以使用const,将其改变成常量。
所以指针返回值的修改也可以改为这样的。
const char *fanhui()
{
//char *p = (char*)malloc(200);
// char p[200];
//char q[100]="李四/student.txt";
// strcpy(p,q);
char const *p = "李四/student.txt";
return p;
}
int main()
{
printf("p = %s\n",fanhui());
}
const char *fanhui()
{
char p[100] = "李四/student.txt";
char const *q = p;
return q;
}
int main()
{
printf("p = %s\n",fanhui());
}
注意此处使用了const 后返回值的类型也必须加上const。此处可以看出返回了理想值。此处涉及了const的许多用法,第二个代码主要是使得指针q的指向的地址不能改变,所以即使程序结束,数组p释放,那块内容是不释放的,那块内容是存在的,只是程序对它失去了操作的权利。但是在后面定义了char const *q = p.这样的操作使得q一直都是指向那块内容的地址,而且在整个程序中是不能够被改变的,所以能够正确的返回所需要的东西。
总结
以上是通过变量怎么存来提出的解决方案。通过最近对这个返回值为指针的东西纠结,也从网上了解了一些东西。要解决此类问题关键在于知道变量是存在哪个区域,而且要了解,那四个内存区在程序中是被怎么使用的,它的释放情况等等。所以接下来可能会对那四块区域进行总结。