一个奇怪的C语言问题,涉及到指针、数组、堆栈、以及printf,希望C语言大神们帮帮忙。

首先,这个问题有点2,下面我开始了。一个2一点的程序:#include<stdio.h>char*f(){chararr[]="hello";returnarr;}voi... 首先,这个问题有点2,下面我开始了。
一个2一点的程序:
#include <stdio.h>
char *f()
{
char arr[]="hello";
return arr;
}
void main()
{
char *p;
p=f();
printf("%s\n",p);
}
我们知道,这个程序打印出来的是乱码,因为那个函数f中的arr数组的空间是分配在栈中的,当函数调用结束时,系统自动回收内存。
但是,这个但是很重要,我们知道,所谓的回收就是把栈顶指针改变,但是栈中的内容不会变,所以如果把打印语句改成
printf("%c\n",*p);
我们就会打印出一个'h',同样,在打印语句中加上
p++;
这条语句,就会打印出'e',如果是p+=2,就会打印出'l'。。。以此类推。

高潮来了:
如果我的main函数是这样的:
void main()
{
char *p;
p=f();
printf("%c\n",*p);
p++;
printf("%c\n",*p);
p++;
printf("%c\n",*p);
p++;
printf("%c\n",*p);
p++;
printf("%c\n",*p);
}
我是想打印hello出来的,可是只有一个h打出来了,后面的是乱码。
我把第一个printf语句删掉后,就会把e打印出来,后面还是乱码。
如果我一次性删两个printf,就会把l打印出来,后面是乱码。
。。。。。。
请问第一个printf语句肿么了,以至于排在后面的printf语句都打印出了乱码,伤不起啊~~~~~。希望高手解救我
展开
 我来答
百度网友e18852f
2011-10-06 · TA获得超过460个赞
知道小有建树答主
回答量:240
采纳率:50%
帮助的人:146万
展开全部
刚才我也没想明白,看到了dripple11的回答,再去想了一下,现在想明白了。他的回答是正确的。

又回头看了一下,发现,lz没有完全搞懂。
顺便鄙视一下whatplay的回答,是个傻X。

printf函数,正如第一个人所说,调用函数printf前先要将形参压栈,这时候要计算*p
所以,第一条printf语句已经把参数算出来并放到栈顶保存了。然后调用printf函数(函数调用需要用到栈建立访问连和控制链,而,原来的函数f执行完了,原本f是在栈顶的,所以,函数f的栈空间释放。数组空间也被释放),printf占用了栈,所以,把原来函数f的栈空间内容修改了。所以,第一条printf语句是可以得到结果的。后面因为arr空间的内容已经被修改,所以,之后的printf语句都得不到结果。

顺便再解释一下printf("%s\n",p);得到的为什么是乱码。
正如上面所说,先计算参数p的值保存栈顶。保存的值为arr的地址。然后调用printf函数,把栈顶空间内容修改了。虽然保存了地址,但是原来的内容已经修改了,所以得不到结果。

whataplay,我只是鄙视你的回答,没有骂你。因为你的回答是答非所问!
森元德NE
2011-10-05 · TA获得超过149个赞
知道答主
回答量:10
采纳率:0%
帮助的人:1.6万
展开全部
都说得啥呀这是,与printf有啥关系?!请不懂的不要误导。这是很简单也是比较典型的局部变量问题。你可以调试一下,编译器会返回以下信息: warning C4172: returning address of local variable or temporary
指的是你返回了 f() 这个函数的局部临时变量;关键问题是,一旦函数返回,那么它所有的局部变量都会被释放,因此 f() 返回时,它的局部变量 arr[] 同样会被释放,此时arr[] 已经不存在了,返回当然错误。(可以返回头一个,比如这个例子arr[0];需要指出的是,返回单个变量这么做是可行的,不过数组就行不通了 )。所以“返回函数的局部数组变量”这是个错误的方式,要克服。
解决方法:1. 将arr申请为静态变量,static char arr[]="hello"; 这样函数反回时静态变量arr就不会被释放了。或者动态申请内存 char *arr= new char [100]; arr = "hello"; 或者干脆 char *arr="hello"; 100表示尽量大一些。打印时候别加星 printf("%s\n", p);
2. 将p在函数外部申请
void f(char *arr)
{
sprintf(arr, "%s", "hello");
}
void main()
{
char p[100];
f(p);
printf("%s\n", p);
}
推荐这一种,说得是最好在函数外面把内存申请工作做好,在函数里面申请的内存只管函数里面的运算作用,最好不要针对外面。希望你通过这个例子对规范化编程有进一步的认识。
请骂我的人放尊重一点,我都编程这么多年了,这个问题不可能弄不明白,谢谢。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
dripple11
2011-10-05 · TA获得超过464个赞
知道小有建树答主
回答量:430
采纳率:0%
帮助的人:295万
展开全部
printf函数里面使用了堆栈,打印后将原有堆栈内容破坏
更多追问追答
追问
请详细解释一下,谢谢啦
追答
执行printf时,首先会把*p的值算出来,这时候堆栈没有破坏,所以第一次可以打印
一旦执行了printf,printf使用到了回收的堆栈,所以后面的内容都被破坏了,后面都是乱码
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
ljf10000
2011-10-06 · TA获得超过199个赞
知道小有建树答主
回答量:125
采纳率:0%
帮助的人:109万
展开全部
printf也是函数,第一个printf调用导致参数压栈,hello被冲掉了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
liber798
2011-10-05 · TA获得超过753个赞
知道答主
回答量:132
采纳率:100%
帮助的人:44.6万
展开全部
请 dripple11 高手详细解答,学习了!~
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(3)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式