求C语言帝

fangjiabinabc 2012-08-28 04:58:57
char * getmemory()
{
char str[]=”hello world”;
return str;
}
int main()
{
char *ptr=getmemory();
printf(“%s\n”,ptr);
return 0;
}
为什么上边的会打印出乱码,而下边的可以正常输出?

void fun(char *p)
{ int a[10];
printf(“%s\n”,p);
}
char * getmemory()
{
char str[]=”hello world”;
return str;
}
int main()
{
char *ptr=getmemory();
fun(ptr);
return 0;
}
int a[10]为什么要加上去,不加也会出现乱码.
...全文
295 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
bigbaldy 2012-08-29
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

这么喜欢较真各种“不应该的行为”,直接看汇编代码就好了
你所想知道的一切,都在汇编代码里展示得一清二楚

为啥局部变量离开函数就失效?因为局部变量占用的是栈内存。定义局部变量的时候栈顶指针上移该局部变量所占的空间,这叫做入栈,函数退出的时候栈顶指针下移,这叫做出栈,变量入栈后有效,出栈后失效
为啥第一个函数输出的是乱码?第一个函数结束后,字符串数组的数据没有改变,但栈顶指针已经移到这块内……
[/Quote]

和“C语言”本身的确没有关系,但是这些东西是学C必须要懂的,楼主又不是在用C#,java,python之类的在写程序,搞C的如果不懂这些你说咋写程序,而用这些高级面向对象编程语言或者脚本语言的,懂不懂这些倒是关系不大
一叶知秋dong 2012-08-29
  • 打赏
  • 举报
回复
一切看似很巧很鬼很匪夷所思滴问题,都有原因
MFCJCK 2012-08-29
  • 打赏
  • 举报
回复
兄弟,这个要从汇编角度来理解。
局部变量都是在栈开辟空间,调用getmemory在栈上分配10字节的空间给变量str使用,退出后,栈会弹出,当进入第二个函数void fun(char *p),要求跟第一个函数进入相同--分配10个字节。于是,栈上原来的str空间就分配给了char a[10]。

总之一句话,地址相同。
shiter 2012-08-29
  • 打赏
  • 举报
回复

#include "stdafx.h"

char * getmemory()
{
char *str="hello world";
return str;
}

int main()
{
char *ptr=getmemory();
printf("%s\n",ptr);
getchar();
return 0;
}

第一个改下,这么就可以啦.静态常量...vs 2010 express测试通过
shiter 2012-08-29
  • 打赏
  • 举报
回复
是不是改成char *p="...."这种就能成?
northcan 2012-08-29
  • 打赏
  • 举报
回复
char * getmemory()
{
char str[]=”hello world”;
return str;
}

getmemory return之后,str已经失效
不要让函数返回局部非静态的变量,即使它偶尔能够正确工作
vc编译器会给出警告:
returning address of local variable or temporary

可以加一个static:
char * getmemory()
{
static char str[]=”hello world”;
return str;
}

shijinpeng_2012 2012-08-29
  • 打赏
  • 举报
回复
哪块刚好分配的10个字符的内存,又刚好没用,所以你打印出来不会出错 你把字符变的再长点试试..
Alexander 2012-08-29
  • 打赏
  • 举报
回复
说穿了就是变量生存期的问题。
baichi4141 2012-08-28
  • 打赏
  • 举报
回复
这么喜欢较真各种“不应该的行为”,直接看汇编代码就好了
你所想知道的一切,都在汇编代码里展示得一清二楚

为啥局部变量离开函数就失效?因为局部变量占用的是栈内存。定义局部变量的时候栈顶指针上移该局部变量所占的空间,这叫做入栈,函数退出的时候栈顶指针下移,这叫做出栈,变量入栈后有效,出栈后失效
为啥第一个函数输出的是乱码?第一个函数结束后,字符串数组的数据没有改变,但栈顶指针已经移到这块内存的下方,它已经出栈,此时再调用printf函数,则进行将当前EIP寄存器入栈、将所调用函数的输入参数从右向左入栈等等,随着栈顶指针的上移,字符串数组的数据所在的内存逐一被纳入栈顶指针的下方并被改写为压栈的数值,于是字符串数组的数据被覆盖,此时再使用之前保存的数组首地址来读取这些数据,结果就是乱码
为啥第二个函数可以输出这些数据?原因就是这些数据没有被覆盖。为啥没有被覆盖?因为这个函数在一开始定义了一个很大的数组并且没有初始化,栈顶指针上移到该块内存之上,原字符串数组的那些数据就被笼罩在了这个数组的范围内没有被改变,此时调用函数时进行的压栈等操作就不会影响到原字符串数组的那些数据,可以原样读出,但如果你在定义第二个函数开头的大数组的时候将之初始化,那么原字符串数组的数据就被全部覆盖掉,那就读不出来了

本质上,计算机中没有“随机”的东西
说“随机”,意思就是“你不用去想,也不该去想”。按照标准写下的代码一定会被编译器编译成能够实现相应功能的机器命令,不按标准写下的代码即使能够通过编译器的语法检查,结果也是“不可控”“未知”“随机”。
这些东西真的是完全不可控未知随机吗?不是,但这些东西不在C语言的范畴内,研究C语言的人不该去研究它们,这些东西应该被研究编译器和汇编语言的人研究。

所以楼主,找什么C语言帝啊?
想知道这些不按标准写下的代码为什么会有相应的结果,去啃汇编语言,去啃编译原理,去啃编译器吧
总之,那和“C语言”没关系
dic_008 2012-08-28
  • 打赏
  • 举报
回复
20分就想让赵老师出马
对了是偶然,打印一个局部变量的内存块,当那个函数结束,那块内存已经无效了,其他程序都能占用。
bigbaldy 2012-08-28
  • 打赏
  • 举报
回复
返回局部指针变量,已经平栈了,就算打印出来的正常,也是你运气好碰上了
fangjiabinabc 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
引用 6 楼 的回复:

引用 1 楼 的回复:
两个都有问题,两个都返回局部数组的地址了,结果对也是偶然的。
红帽编译,linux系统,第二个没有错误。第一个编译通过,打印是乱码


傻孩子,结果现在对,不代表他一直会对。
函数执行完成,函数调用栈内存释放,只是标记为未使用,并未设置为0或其它值。
而你还在使用函数返回的函数局部数组的地址。
这种行为是未定义的,也就是一种错误……
[/Quote]
那在第二个代码中为什么要加上int a[10]呢?加int a[1]什么的也可以的。但是不加的话就直接输入乱码了。
冻结 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

引用 1 楼 的回复:
两个都有问题,两个都返回局部数组的地址了,结果对也是偶然的。
红帽编译,linux系统,第二个没有错误。第一个编译通过,打印是乱码
[/Quote]

傻孩子,结果现在对,不代表他一直会对。
函数执行完成,函数调用栈内存释放,只是标记为未使用,并未设置为0或其它值。
而你还在使用函数返回的函数局部数组的地址。
这种行为是未定义的,也就是一种错误行为。
fangjiabinabc 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
两个都有问题,两个都返回局部数组的地址了,结果对也是偶然的。
[/Quote]红帽编译,linux系统,第二个没有错误。第一个编译通过,打印是乱码
Code_Talk 2012-08-28
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
第二个程序是错的, 输出正常可能的原因是:
1. 函数全部被编译器优化成内联函数了
2. str 所指向的内存虽然不应该使用, 但是它还没有被其它人写入, 内容就没变. int a[10]; 刚好映射到这个地址上, 有没有写操作, 起到了一个保护作用.
[/Quote]
高手。
backbin 2012-08-28
  • 打赏
  • 举报
回复
两个都有问题,两个都返回局部数组的地址了。

结果是对的吗,我测试的是乱码VS2005亲测
www_adintr_com 2012-08-28
  • 打赏
  • 举报
回复
第二个程序是错的, 输出正常可能的原因是:
1. 函数全部被编译器优化成内联函数了
2. str 所指向的内存虽然不应该使用, 但是它还没有被其它人写入, 内容就没变. int a[10]; 刚好映射到这个地址上, 有没有写操作, 起到了一个保护作用.
allenbein 2012-08-28
  • 打赏
  • 举报
回复
你这结果必然错,下面能打印是因为在fun函数里面打印的而已。
而且打印出来估计都是:烫烫烫烫烫烫烫烫烫烫烫烫烫烫,因为内存中CC翻译过来就是烫。
你可以用指向数组的指针做参数,把数组给返回出来(数组的有效域在函数之外)再打印就行了。
冻结 2012-08-28
  • 打赏
  • 举报
回复
两个都有问题,两个都返回局部数组的地址了,结果对也是偶然的。
第一章关键字...................................................................................................................................9 1.1,最宽恒大量的关键字----auto..........................................................................................11 1.2,最快的关键字---- register............................................................................................... 11 1.2.1,皇身边的小太监----寄存器............................................................................. 11 1.2.2,使用register 修饰符的注意点.............................................................................11 1.3,最名不符实的关键字----static........................................................................................12 1.3.1,修饰变量...............................................................................................................12 1.3.2,修饰函数...............................................................................................................13 1.4,基本数据类型----short、int、long、char、float、double........................................... 13 1.4.1,数据类型与“模子”............................................................................................... 14 1.4.2,变量的命名规则...................................................................................................14 1.5,最冤枉的关键字----sizeof...............................................................................................18 1.5.1,常年被人误认为函数...........................................................................................18 1.5.2,sizeof(int)*p 表示什么意思?........................................................................18 1.4,signed、unsigned 关键字................................................................................................19 1.6,if、else 组合.................................................................................................................... 20 1.6.1,bool 变量与“零值”进行比较...............................................................................20 1.6.2, float 变量与“零值”进行比较.................................................................................21 1.6.3,指针变量与“零值”进行比较...............................................................................21 1.6.4,else 到底与哪个if 配对呢?...............................................................................22 1.6.5,if 语句后面的分号............................................................................................... 23 1.6.6,使用if 语句的其他注意事项.............................................................................. 24 1.7,switch、case 组合........................................................................................................... 24 1.7.1,不要拿青龙偃月刀去削苹果.............................................................................. 24 1.7.2,case 关键字后面的值有什么要吗?.............................................................. 25 1.7.3,case 语句的排列顺序...........................................................................................25 1.7.4,使用case 语句的其他注意事项..........................................................................27 1.8,do、while、for 关键字................................................................................................... 28 1.8.1,break 与continue 的区别.....................................................................................28 1.8.2,循环语句的注意点...............................................................................................29 1.9,goto 关键字......................................................................................................................30 1.10,void 关键字....................................................................................................................31 1.10.1,void a?............................................................................................................31 1.10,return 关键字................................................................................................................. 34 1.11,const 关键字也许该被替换为readolny....................................................................... 34 1.11.2,节省空间,避免不必要的内存分配,同时提高效率.................................... 35 1.12,最易变的关键字----volatile.......................................................................................... 36 1.13,最会带帽子的关键字----extern.................................................................................... 37 1.14,struct 关键字..................................................................................................................38 1.14.1,空结构体多大?.................................................................................................38 1.14.2,柔性数组.............................................................................................................39 1.14.3,struct 与class 的区别.........................................................................................40 1.15,union 关键字..................................................................................................................40

70,035

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧