C语言中以字符串为返回值的函数的问题,困扰我好几天了
下面是课本上讲述野指针时的范例代码#include<stdio.h>#include<string.h>char*Getstr(void);intmain(){char*...
下面是课本上讲述野指针时的范例代码
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char *ptr = NULL;
printf("Input a string");
ptr = Getstr();
puts(ptr); //试图使用野指针,导致程序输出出现乱码
}
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
但是当我把程序改成下面这样时,虽然仍然有警告错,但是却能正确输出
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char str[80];
printf("Input a string");
strcpy(str,Getstr());//没有直接用Getstr()的返回值,而是把Getstr()的内容复制给str
puts(str);
}
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
再次实验,把puts函数改成printf,仍然能得到正确的结果,也就是把最开始的代码改成下面这样
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char *ptr;
printf("Input a string");
ptr = Getstr();
printf("%s",ptr); //不用puts,改用printf
}
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
为什么会有这种状况?按书上说,子函数退出之后,所占有的栈内存被释放,为什么还能被strcpy和printf使用,得到正确的输出?更奇怪的是,为什么只有puts函数不能使用函数返回的字符串,而输出乱码?
以上代码在VC++6和gcc下运行结果相同。 展开
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char *ptr = NULL;
printf("Input a string");
ptr = Getstr();
puts(ptr); //试图使用野指针,导致程序输出出现乱码
}
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
但是当我把程序改成下面这样时,虽然仍然有警告错,但是却能正确输出
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char str[80];
printf("Input a string");
strcpy(str,Getstr());//没有直接用Getstr()的返回值,而是把Getstr()的内容复制给str
puts(str);
}
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
再次实验,把puts函数改成printf,仍然能得到正确的结果,也就是把最开始的代码改成下面这样
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char *ptr;
printf("Input a string");
ptr = Getstr();
printf("%s",ptr); //不用puts,改用printf
}
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
为什么会有这种状况?按书上说,子函数退出之后,所占有的栈内存被释放,为什么还能被strcpy和printf使用,得到正确的输出?更奇怪的是,为什么只有puts函数不能使用函数返回的字符串,而输出乱码?
以上代码在VC++6和gcc下运行结果相同。 展开
4个回答
展开全部
野指针的含义:超出生命周期的指针,包括函数内局部数据的指针(static修饰数据除外,它不在栈上)和已经被释放了的动态分配内存区。
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
这个函数,是将栈内局部变量的地址返回给调用者,调用者拿到的指针属于典型的超出生命周期的指针,对它的使用会不会引起错误,依赖于进一步的操作,本身行为就是不可预期的。
可以认为:使用strcpy和printf并没有破坏这个内存区域,即没有对这部分内存做修改,因此运行可以得到你期待的结果。但puts的运行修改了这部分内存区,导致你看到的都是乱码。
避免野指针带来的不确定性:
你可以使用
char *Getstr(void)
{
static char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
用这个函数,你的所有逻辑都不变。
或者
char *Getstr(void)
{
char *s = malloc(80);
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
要记得在这个调用后得到的ptr,一定要用free(ptr)。
char *Getstr(void)
{
char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
这个函数,是将栈内局部变量的地址返回给调用者,调用者拿到的指针属于典型的超出生命周期的指针,对它的使用会不会引起错误,依赖于进一步的操作,本身行为就是不可预期的。
可以认为:使用strcpy和printf并没有破坏这个内存区域,即没有对这部分内存做修改,因此运行可以得到你期待的结果。但puts的运行修改了这部分内存区,导致你看到的都是乱码。
避免野指针带来的不确定性:
你可以使用
char *Getstr(void)
{
static char s[80];
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
用这个函数,你的所有逻辑都不变。
或者
char *Getstr(void)
{
char *s = malloc(80);
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
要记得在这个调用后得到的ptr,一定要用free(ptr)。
展开全部
一、不要使用局部变量作为返回值来使用!因为,子函数一结束,局部变量就被释放。
当有其它程序用到该内存数据时,数据就会发生变化,
而若没有人使用,则数据不会发生变化。
二、一定要使,则将局部变量定义成静态变量,相当于定义一个全局变量:
char *Getstr(void)
{
static char s[80]; //加上static
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
当有其它程序用到该内存数据时,数据就会发生变化,
而若没有人使用,则数据不会发生变化。
二、一定要使,则将局部变量定义成静态变量,相当于定义一个全局变量:
char *Getstr(void)
{
static char s[80]; //加上static
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
子函数结束之后所占的内存被释放掉意思是“这片内存空间从释放掉之后就可以再次被其他程序使用”,但是这片空间里的内容有没有改变就不好说了,程序输出正确的结果只能说明在你函数返回到调用fputs这段时间里这片内存没有被重新赋其他的值。虽然结果是正确的,语法上也没有错误,但是这种写法是不对的!只要是被释放掉的内存空间绝对不可以再次引用!
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
#include <stdio.h>
#include <string.h>
char *Getstr(void);
int main()
{
char str[80];
printf("Input a string");
strcpy(str,Getstr());//没有直接用Getstr()的返回值,而是把Getstr()的内容复制给str
puts(str);
return 0;
}
char s[80];//声明为全局变量
char *Getstr(void)
{
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
#include <string.h>
char *Getstr(void);
int main()
{
char str[80];
printf("Input a string");
strcpy(str,Getstr());//没有直接用Getstr()的返回值,而是把Getstr()的内容复制给str
puts(str);
return 0;
}
char s[80];//声明为全局变量
char *Getstr(void)
{
scanf("%s",s);
printf("s = %p\n",s);
return s;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询