函数底层传参和返回值解析

函数调用栈

func A(){
	...
	...
}
func B(){
	...
	...
}

我们按照编程语言的语法定义的函数,会被编译成一堆机器指令,写入可执行文件,程序执行时,可执行文件加载到内存,这些机器指令对应到虚拟地址空间中,位于代码段,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tv5o6kSB-1646901328779)(D:\鹰飞计划\图片\image-20220310142253760.png)]

如果在一个函数中调用另一个函数,编译器就会对应生成一条call指令,程序执行到这条指令的时候,就会跳转到被调用函数入口处开始执行,每个函数的最后都有一条ret指令,负责在函数结束后跳回到调用处,继续执行。

函数栈帧

函数执行时需要有足够的内存空间,供它存放局部变量,参数等数据,这段空间对应到虚拟地址空间的栈,分配给函数的空间称为函数栈帧

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-05iOCT9R-1646901328780)(D:\鹰飞计划\图片\image-20220310145144806.png)]

call指令只做两件事:

  • 第一件将下一条指令的地址入栈,就是返回地址,被调用函数执行结束后会跳转回这里.
  • 第二件跳转到被调用的函数入口处执行
函数传参
值传递

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1XwtUkiw-1646901328782)(D:\鹰飞计划\图片\image-20220310153021971.png)]

传参是值拷贝,所以拷贝整形变量a,b的值,由图可以知道a,b值交换失败的原因了,交换的并不是局部变量的a,b

注意:参数入栈顺序是由右向左

指针传递

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OP1YCEj6-1646901328783)(D:\鹰飞计划\图片\image-20220310155038327.png)]

交换成功,交换的是两个指针指向的数据。

函数返回值

案例1:(匿名返回值)

func incr(a int)int{
	var b int
	defer func(){
		a++
		b++	
	}
	a++
	b=a
	return b
func main(){
	var a,b int
	b=incr(a)
	fmt.Println(a,b)//0,1
}

程序未执行时在栈中地址分布如图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlK3vrXZ-1646901328785)(D:\鹰飞计划\图片\image-20220310160904578.png)]

由函数可知,incr函数中a先自增1,栈中args变成1,执行到b = a时,被调用函数BP of incrb = 1,到return时,先会把局部变量b的值拷贝到返回值空间,return value中0变成1,然后在执行注册的defer函数再return,因为a++所以args中变成2,执行b++时,被调用函数BP of incrb = 2

incr函数结束,栈中结果如下:
在这里插入图片描述

案例2:(命名返回值)

func incr(a int)(b int){
	defer func(){
		a++
		b++//返回值b自增一
	}()
	a++
	return a
}
func main(){
	var a,b int
	b = incr(a)
	fmt.Println(a,b)//0,2
}

最终执行情况如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值