OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5692|回复: 6

C++ 教程源码求指导~

[复制链接]

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
发表于 2016-1-29 15:49:58 | 显示全部楼层 |阅读模式
5金钱
QQ截图20160129145540.png
如上代码程序是<<C++ primer plus>>教程源码,小弟心中有个疑惑,恳请大神指导~
我记得我在学习C的过程中,公司同事跟我说过:在被调用函数中:如果函数的返回值是某个局部变量,或者某个局部变量的地址,那么这个返回值是不确定的,因为局部变量时放在栈内存中的,如果退出这个函数,这个局部变量所在的内存是不确定的.
现在在学习C++的过程中,我想请教大神帮我指点下~
问题1:在C编译器环境下,这句话是正确的吗???
问题2:如果将C编译环境换为C++编译环境,那么这句话还能同样成立吗?如果成立的话,那上面的这段程序该如何解释???
恳请大神指教~~~

最佳答案

查看完整内容[请看2#楼]

“在被调用函数中:如果函数的返回值是某个局部变量,或者某个局部变量的地址,那么这个返回值是不确定的,因为局部变量时放在栈内存中的,如果退出这个函数,这个局部变量所在的内存是不确定的” 问题1: 如果返回的是局部变量的值,是没有问题的;但是如果返回的是被调用函数局部变量的地址,就会有可能有问题,因为这个局部变量的地址在栈中,当你退出这个函数的时候,或许发生其他函数调用或中断,就会将这个栈地址的值刷新掉, ...
电子爱好者
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-1-29 15:49:59 | 显示全部楼层
本帖最后由 ianhom 于 2016-1-29 22:17 编辑

“在被调用函数中:如果函数的返回值是某个局部变量,或者某个局部变量的地址,那么这个返回值是不确定的,因为局部变量时放在栈内存中的,如果退出这个函数,这个局部变量所在的内存是不确定的”

问题1:
如果返回的是局部变量的值,是没有问题的;但是如果返回的是被调用函数局部变量的地址,就会有可能有问题,因为这个局部变量的地址在栈中,当你退出这个函数的时候,或许发生其他函数调用或中断,就会将这个栈地址的值刷新掉,你就得到个错误的值。

问题2:
我个人觉得C++也是一样的,虽然p是个临时指针变量,这个指针变量的地址是在栈中,但是这个函数返回的是这个指针变量的值,而这个值为new出来的一个堆区域的一个地址(类似于C的malloc),堆是程序员申请释放的区域,不会像栈那样被刷新,故上层函数获得这个返回值----堆区域的一个地址就可以正常操作。

举个例子
[mw_shl_code=c,true]int Test1()
{
    int a = 0;      /* 局部整型变量,a的地址在栈中(如果不反馈a的地址的话,其实a在通用Rx中,) */
    a = GPIOA & 0x01 /* 获取某个IO的高低电平 */
    return a;     /* 返回局部变量的值,为IO的电平,合法 */
}[/mw_shl_code]

[mw_shl_code=c,true]int* Test2()
{
    int a = 0; /* 局部整型变量,a的地址在栈中(因为需要操作a的地址,a一定会放到栈中) */
    int *p = &a;   /* 获取a的地址 */
    *p = GPIOA & 0x01 /* 获取某个IO的高低电平 */
    return p; /* 返回的是栈中的地址,退出该函数后,这个栈地址很可能会被其他函数或中断调用,故使用这个地址上的值是危险的 */
}[/mw_shl_code]

[mw_shl_code=c,true]int* Test3()
{
    int *p = (int*)malloc(sizeof(int));   /* 类似new,从堆区域申请一个int的空间,并把地址给指针变量p*/
    *p = GPIOA & 0x01 /* 获取某个IO的高低电平 */
    return p; /* 返回的是堆中的地址,退出该函数后,除非程序员自己free到这个区域,不然这个地址的值是程序员可控的,安全 */
}[/mw_shl_code]


我调整了下上面的代码,做了个小实验,可以参考一下:
调用test1()
QQ截图20160129212823.png

QQ截图20160129213146.png

QQ截图20160129213203.png

调用test2()
QQ截图20160129214827.png

QQ截图20160129215012.png

QQ截图20160129215208.png

QQ截图20160129215553.png

调用Test3()
QQ截图20160129220045.png

QQ截图20160129220426.png

QQ截图20160129220644.png
机器生汇编,汇编生B,B生C,C生万物.... 经过长期对C语言的研究,目前只有两个方面不懂:这也不懂,那也不懂
https://github.com/ianhom
回复

使用道具 举报

5

主题

163

帖子

0

精华

高级会员

Rank: 4

积分
615
金钱
615
注册时间
2011-11-7
在线时间
180 小时
发表于 2016-1-29 22:13:59 | 显示全部楼层
构造和析构?
回复

使用道具 举报

18

主题

422

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1139
金钱
1139
注册时间
2014-5-24
在线时间
116 小时
发表于 2016-1-29 23:34:08 | 显示全部楼层
你同事口述不精确,但是有意义的。
楼主位返回的地址不属于局部变量,返回是正确的。
I See Fire.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.·.  只给方向,不妨碍思考
回复

使用道具 举报

54

主题

125

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
369
金钱
369
注册时间
2015-7-10
在线时间
17 小时
发表于 2016-1-30 17:21:04 | 显示全部楼层
函数返回的始终是一个确定的值,而变量不是值,只是一个称呼。
回复

使用道具 举报

34

主题

805

帖子

4

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1863
金钱
1863
注册时间
2011-3-29
在线时间
139 小时
发表于 2016-1-30 23:15:25 来自手机 | 显示全部楼层
值传递的话绝对没问题,地址传递的话看所在地址是什么。new生成的对象所在地址在堆里,传递这个地址就没问题。如果对象是在栈里的,函数返回后会释放栈空间给中断函数等使用,这时候对象地址的内容就有可能被改变。
回复

使用道具 举报

119

主题

439

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1185
金钱
1185
注册时间
2015-9-18
在线时间
422 小时
 楼主| 发表于 2016-2-2 08:56:20 | 显示全部楼层
ianhom 发表于 2016-1-29 15:49
“在被调用函数中:如果函数的返回值是某个局部变量,或者某个局部变量的地址,那么这个返回值是不确定的,因为 ...

每次都能聆听大神指点,再次谢过~
电子爱好者
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 02:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表