ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浅谈Golang函数调用栈-传参和返回值

2021-10-31 17:05:08  阅读:244  来源: 互联网

标签:浅谈 局部变量 函数调用 Golang 参数 返回值 栈帧 函数


函数调用栈-传参和返回值

defer与return时机

return赋值和返回是两个步骤,不是原子操作,如果有defer会插在两个步骤中:

  1. 返回值赋值(return value)
  2. defer语句 //可有可无
  3. 返回值返回

传值的swap函数

在这里插入图片描述
我们通过函数调用栈看看问题到底出在哪
在这里插入图片描述

假设main函数栈帧在这里,先分配局部变量locals,这里函数调用没有返回值,所以局部后面就是给被调用函数传入的参数args,注意参数入栈顺序由右到左,返回值也是一样,这样被调用函数通过sp+偏移寻址就比较方便了,调用者栈帧后面存的是下一条指令的地址,在下面分配的就是swap函数栈帧了,当swap函数执行到a,b=b,a时,要交换两个参数的值
在这里插入图片描述
把值交换一下
在这里插入图片描述
现在,交换失败的原因找到了,调用者的局部变量a和b在这里,交换的并不是它们

传指针的swap函数

在这里插入图片描述
我们通过函数调用栈看看和上一次有什么不同
在这里插入图片描述

main函数栈帧先分配局部变量,然后分配参数空间,参数是指针,传参都是值拷贝,这里拷贝的就是a和b的地址,在后面是返回地址以及swap函数栈帧

在这里插入图片描述
swap执行到*a,*b=*b,*a时,交换的是这两个指针指向的数据,也就是这两个地址的数据,所以这一次能交换成功

匿名返回值函数

通常我们认为返回值是通过寄存器传递的,但是go语言支持多返回值,所以在栈上分配返回值空间更合适
在这里插入图片描述
这里main函数调用incr函数,然后赋给局部变量b,来看看函数调用栈的情况。
在这里插入图片描述

main函数栈帧,先是局部变量a=0,b=0,然后是incr的返回值,初始化为类型零值,然后是参数,传参值拷贝,最后是返回地址。到incr函数栈帧这里,保存调用者main的栈帧地址后,初始化局部变量b
在这里插入图片描述
执行到这里,要把参数a自增1,而参数a在这
在这里插入图片描述
下一步,把参数a赋给局部变量b。到return这里,必须要明确一个关键问题。我们说过函数最后有编译器插入的指令,负责释放函数栈帧,恢复到调用者栈,但在这之前要给返回值赋值并执行defer函数,那谁先?谁后?答案是先赋值
在这里插入图片描述
所以执行到return b这里,会先把局部变量b的值拷贝到返回值空间
在这里插入图片描述
然后再执行注册的defer函数,defer函数里,这一步a再次自增1,下一步局部变量b也自增1,然后incr结束。
在这里插入图片描述
返回值为1 ,赋给main函数的局部变量b,所以最后会输出0和1

具名返回值函数

在这里插入图片描述
其他都不变,只把这里的局部变量b,改成命名返回值,看看有什么不同

在这里插入图片描述
main函数栈帧与上一例完全相同,到incr函数栈帧这里,没有局部变量,当执行到a++时,参数a自增1
在这里插入图片描述
return这里,先把参数a赋给返回值b

在这里插入图片描述
然后执行defer函数,参数a再次自增1,下一步,返回值b也自增1,然后incr结束,返回值最终为2,所以main的局部变量b赋值为2,最终输出0和2

调用多个函数的小问题

在这里插入图片描述

如果一个函数A调用了两个函数B和C。但是这两个函数的参数和返回值,占用的空间并不相同,我们知道Go语言的函数栈帧是一次性分配的,如果局部变量占这么大,这后面还要以最大的参数加返回值空间为标准来分配,才能满足所有被调函数的需求
在这里插入图片描述
B的参数和返回值可以把这里占满没有问题
在这里插入图片描述
但是B结束后调用C时,它的参数和返回值,只会占用下面这段空间,虽然上面空出来一块,但是被调用者,通过栈指针相对寻址自己的参数和返回值时会比较方便

标签:浅谈,局部变量,函数调用,Golang,参数,返回值,栈帧,函数
来源: https://blog.csdn.net/qq_42956653/article/details/121065713

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有