怎么理解函数的返回值(感觉挺有意思,请高手探讨)

wylove 2005-08-17 03:34:29
int *fun()
{
int a = 5;
return &a;
}
int main()
{
int *a = fun();
cout << *a;//结果是5,结果正确
}
一般的理解:由于a是局部变量,存储在函数所在的栈中,生存期为函数的执行期。
因此,返回其地址是无效的。但实际在调用中,返回的值仍然是正确的。
这意味着两点:
1、栈的空间释放后,还保留该内存地址的值(自己也不确定)
2、5本身在文字常量区,不在栈内,因此返回的是常量5的地址;
...全文
507 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
wylove 2005-08-19
  • 打赏
  • 举报
回复
大家说的都很好,根据上面高手的想法,我试了一下:
int *fun()
{
int a = 5;
cout << &a;//增加改行代码
return &a;
}
int main()
{
int *a = fun();
cout << *a;//结果是不在是5,结果正确
}
看了一下汇编代码如下:
236: int* fun2()
237: {
00401E50 push ebp
00401E51 mov ebp,esp
00401E53 sub esp,44h
00401E56 push ebx
00401E57 push esi
00401E58 push edi
00401E59 lea edi,[ebp-44h]
00401E5C mov ecx,11h
00401E61 mov eax,0CCCCCCCCh
00401E66 rep stos dword ptr [edi]
238: int a = 5;
00401E68 mov dword ptr [ebp-4],5
239: cout << &a;
00401E6F lea eax,[ebp-4]
00401E72 push eax
00401E73 mov ecx,offset std::cout (0047f7f8)
00401E78 call @ILT+110(std::basic_ostream<char,std::char_traits<char> >::operator<<)
244: return &a;
00401E7D lea eax,[ebp-4]
245: }
别的代码应该不会对ebp-4这个临时存储区产生影响,关键是:
00401E78 call @ILT+110(std::basic_ostream<char,std::char_traits<char> >::operator<<)
估计对临时缓冲区进行了操作。
不太理解是什么时候影响了临时存储区ebp-4内存储的值,希望高手能够指点。
HaoyuTan 2005-08-18
  • 打赏
  • 举报
回复
每一个编译器具体的实现不同。

有的会在函数返回时立即释放栈空间并将值设为随机值,有的编译器考虑到效率的问题会将该栈空间标识为“可用”但不去对其中的值做操作,于是就有了楼主说的情况,有的可能将所有需要被释放的栈空间收集起来然后在某个时刻一起释放,也会有楼主的情况。

但是这种情况只是因为编译器的具体实现不同引起的,并不表示它总是安全的。

---------------------------------------------------------------------------------------

C/C++,asm都不存在栈空间收集,回收的问题,也不需要有释放的概念
lyclowlevel 2005-08-18
  • 打赏
  • 举报
回复
1.栈空间根本没有释放的概念,唯一变动的只是栈指针,也就是esp和ebp两个寄存器

2.显然是错误的。
5是文字常量不错的。
但,int a=5;
实际上是,重新在栈内分配空间,然后将
5赋给a关联的那个空间。
不然的话,文字常量存放的那个内存是被
编译器解释成const的。像你说的那样,
a=6;就是错误的。
你看一下下面的例子:
char *p="const";
p[1]='o';
cout<<p<<endl;
编译和链接都没事,但运行却出错了,
提示“修改了一片只读内存的值”。
zhousheng198 2005-08-18
  • 打赏
  • 举报
回复
返回的不是地址,是在返回过程中程序自动把地址转化成了整数.
HaoyuTan 2005-08-18
  • 打赏
  • 举报
回复
栈就素浮云....
SeaKing911 2005-08-18
  • 打赏
  • 举报
回复
应该是函数返回后只是修改了栈空间的指针而已,并没有操作覆盖内容或者清空内容.
黄昏清晨 2005-08-18
  • 打赏
  • 举报
回复
还能得到5,是因为没有其他数据把原来存5的内存覆盖掉而已。
晨星 2005-08-18
  • 打赏
  • 举报
回复
你再中间再调用一个函数试试看。比如:

int *fun()
{
int a = 5;
return &a;
}
int main()
{
int *a = fun();
cout << "abcdefg" << endl;
cout << *a;//结果是5,结果正确
}
你刚调用万fun,中间没有做任何事,系统当然不会闲着无聊帮你把用过的栈空间清零一下,因为没这个必要,浪费时间。系统知道你一般不会去打印一个已经无效的地址里的数据,既然不会,那么何必要清零呢?暂时就保存着原来的值好了,有什么大不了的。总之待会儿谁要用这块位置就给他用好了,比如上面的例子,栈里的5就被另外一次operator <<调用给冲掉了。
sunlu_eric 2005-08-18
  • 打赏
  • 举报
回复
应该是那个空间没有被别的函数或操作改写!
leon_0225 2005-08-17
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

int *fun1()
{
int a = 5;
return &a;
}

int *fun2()
{
int a = 6;
return &a;
}

int main()
{
int *a = fun1();
fun2();
cout << *a;//结果是6,结果不正确
}


diandian82 2005-08-17
  • 打赏
  • 举报
回复
软件开发千万不要这样啊。否则也可能测试没事,演示没事,但在你最重要的客户面前崩溃掉
Sandy_Y 2005-08-17
  • 打赏
  • 举报
回复
不如上机试试
fujike029 2005-08-17
  • 打赏
  • 举报
回复
int *fun()
{
int a = 5;
cout<<&a<<endl;;
return &a;
}
int main()
{
int *a = fun();
cout << a<<endl; //估计就不同了/ 可能是a的地址,不确定/
cout << *a;//结果是5,结果正确

}

bugebear3 2005-08-17
  • 打赏
  • 举报
回复
函数的返回值一定不能是临时变量的地址,这是天经地义的事,呵呵
neogeo1984 2005-08-17
  • 打赏
  • 举报
回复
每一个编译器具体的实现不同。

有的会在函数返回时立即释放栈空间并将值设为随机值,有的编译器考虑到效率的问题会将该栈空间标识为“可用”但不去对其中的值做操作,于是就有了楼主说的情况,有的可能将所有需要被释放的栈空间收集起来然后在某个时刻一起释放,也会有楼主的情况。

但是这种情况只是因为编译器的具体实现不同引起的,并不表示它总是安全的。
HaoyuTan 2005-08-17
  • 打赏
  • 举报
回复
楼主错了~~~

1.1、栈的空间释放后,还保留该内存地址的值(自己也不确定)

----------------------------------------------------------
栈空间根本没有释放的概念,唯一变动的只是栈指针,也就是esp和ebp两个寄存器




2、5本身在文字常量区,不在栈内,因此返回的是常量5的地址;

-----------------------------------------------------------
5显然在栈内
qfeng_zhao 2005-08-17
  • 打赏
  • 举报
回复
你函数返回后,对应的变量的内存区域可能还没被重新分配
所以结果可能是正确的,只能说明你这次比较幸运
Mars_xlb 2005-08-17
  • 打赏
  • 举报
回复
同意楼主说的地址还没有变!
但是输出的值是5因该是巧合的吧!如果你在做几个操作的话,然后把输出结果方在最后,我觉得结果就可能产生变化!
int *fun()
{
int a = 5;
cout<<&a<<endl;;
return &a;
}
int main()
{
int *a = fun();
cout << *a;//结果是5,结果正确

}
xiaoqing001 2005-08-17
  • 打赏
  • 举报
回复
生存期为函数的执行期>>>>>>>>>>返回其地址是无效的
healer_kx 2005-08-17
  • 打赏
  • 举报
回复
栈返回后你没有调用啥复杂的函数,你在函数的返回和调用<<之间再加上一些调用再看看。
退栈只是栈顶地址变化而已。

65,187

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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