前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【答疑解惑】C/C++参数传递

【答疑解惑】C/C++参数传递

作者头像
程序员互动联盟
发布2018-03-14 15:15:23
8180
发布2018-03-14 15:15:23
举报
有群友问如下一个问题,他说在下图中sun函数内部的打印是对的,但是为什么调用结束之后主调的结果确是错误的。也就是说,函数sun为什么不能把相加的结果带回主调函数?

要正确理解这个问题,就要了解C/C++语言的参数传递,以及变量在内存中的存储这两个问题,这两个问题其实也是初学者在C/C++学习很容易出现的问题。

C/C++的参数传递

C/C++规定参数传递用于都是传递数值,而不会把参数的地址传递给子函数。注意不要把指针作为参数混为一谈,以为指针就是传递了参数的地址!本质上指针也是传递的一个数值,初学者一定要理解这点。比如以下两个代码片段:

int fun(int n, int *pn)

{

}

int main(void)

{

int a = 5;

int b;

fun(a, &b);

}

在函数fun传递a和&b时,是将a的数字(5)和b的地址这个数字传给子函数,虽然在这里第二个参数的意义是一个变量的地址没错,但是在传给fun时,它只认为他是一个数,不会因为加了&符号就把它认为是一个变量的地址。比如b的地址为0x00401234,也就是&b为0x00401234,但是在汇编层面的参数传递(可能放到寄存器中,也可能放到某个内存地址),它只管把0x00401234这个数值传给子函数,不会关心这个数本身是一个地址,还是地址的地址,甚至地址的n次方地址^_^,所以说C/C++传递的永远都是值传递。至于在子函数里面你想怎么理解这个数,那是你在编写子函数的时候决定的,所以C/C++中你可以把指针作为整数进行运算,这也是C/C++灵活的一个方面。

变量在内存中的存储

这个问题网上有大量的文章,程序员互动联盟网站(http://www.coderonline.net)以及以往的文章中也出现过,这个只是强调一下在子函数中申请的变量(包括形参变量)都是在调用子函数是有栈指针ESP直接移动产生的。也就是说当需要一个栈中的变量时,栈指针就一定一个位置,于是留下一个32位的内存空间就作为这个变量的存储空间。这个过程在所有的函数中都一样,也包括主函数。这里需要强调的是每个函数在调用时都有一个栈帧(基地址就是BSP寄存器决定)。所以实际上每一个函数内部的变量内存单元都可能跟其他不一样,因为他们的栈帧都很可能不同,位置也就不同了。至于什么静态变量、全局变量等等就不在这里讨论,因为跟今天的这个问题没有什么关系。

OK,现在两个概念都基本说清楚了,我们来分一下这个问题是怎么出现的。

首先,主函数分配了三个变量c、d、f (a,b,sum作为指针变量在这里意义不大,可以直接传变量的地址),并在调用子函数时把三个变量c、d、f的地址作为数值传递给sun这个函数。根据上面的分析,c、d、f这三个变量的内存单元是在主函数main这个栈帧里面存在。在子函数处理时,定义了一个变量s,这个s在子函数的栈帧中,用于接收形参a和b这个数值分别作为指针所指向的内存单元的值的和。到这里为止,一切都很正常。但是接下来的一句sum = &s这个语句把一切都搞砸了。我们看看sum是主函数传递过来的f的地址这个数值,假设这个数值是0x00401234,但是这里我们看到它把sum重新改写为s的地址,假设为0x00405678,原本sum的数值是一个位于主函数栈帧中的存储单元f的地址,也是希望向这个地址中0x00401234写入结果,自然就能再主函数中访问的,但是现在换成了一个子函数sun栈帧中的一个变量的地址0x00405678。所以在子函数中打印这个sum所指向的地址的值(s)是没有问题的,但子函数已把f的地址偷梁换柱了,执行完后,主函数的f的地址所在的单元0x00401234根本没有被赋过值,所以主函数的f原来是什么还是什么。

理解之后,要正确解决这个问题就是不要覆盖sum这个数,并且把加的结果放到sum这个里面即可,比如*sum = s。

总结起来就是,本来要用sum这个包接收物品,但是子函数却另外拿了一个包替换了这个包,并且往新的包里放了,原来那个包的所有者把包收回去后,当然在包里面没有想要的物品。但是要理解整个过程,需要理解上面的两个方面的C/C++知识。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员互动联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档