变量 & 地址 & 指针
变量名相对于地址来说,更像是地址的别名。
在声明变量的时候,系统在内存中划分一片地址,并把这片地址命名为<变量名>,
而对变量的赋值, 则是在地址中存入内容, 这个内容常被叫做字面量literal
变量名和地址是一一对应的关系,不可以对地址进行复制操作,会报错。 但可以设置指针指向地址
a:=1
var b int
var c int
&c = &a //这种是不允许的 会报 cannot assign to &d (value of type *int) 不可以直接给地址赋值
var d *int
d = &a //这种是允许的 因为这里d是一个指针
"="只能给同类型赋值
实参 & 形参
实参和形参的主要区别是在函数调用的时候,当传入实参并且在函数操作的时候,并不是直接把实参传过去,而是新建形式参数。
func plus(x, y int) int {
fmt.Print("&x &y : ", &x, &y)
return x + y
}
func main() {
a := 1
b := 2
fmt.Println("&a &b : ", &a, &b)
plus(a, b)
}
/*
&a &b : 0xc0000aa058 0xc0000aa070
&x &y : 0xc0000aa0a0 0xc0000aa0a8
*/
可见实参和形参是完全不一样的两块地址
-
交换变量
所以说由以上,在交换变量的时候,我们只传给实参的变量是没有用的,因为对形参的内容变化 无法返回给实参,形参在函数结束之后就消失了。那只能将传要变换的变量的地址,将地址传给形参进行操作,对地址的影响会影响到世纪我们想要改变的变量
func main(){ a:=1 b:=2 exchange(&a,&b) fmt.Println(a,b) } func exchange(a, b *int) { var c int c = *a *a = *b *b = c }
只有这样,才能实现交换两个变量的值,而直接传变量值是实现不了实参的交换,只能实现形参的交换。
-
scanf()
scanf()也是需要接受地址,因为scanf的源码在调用的时候也是新建的形参,需要对变量的地址动手脚才可以把值传递进去。 实参通过值的方式传递,因此函数的形参是实参的copy,对形参修改不会影响实参,但是如果实参包括引用类型,如指针,slice,map,function,channel等类型,实参可能会由于函数的简介作用被修改
var name2 string
var num float64
fmt.Scanf("%s\n%f", &name2, &num) //输入时严格保证“%s\n%f”格式
fmt.Printf("姓名%s\n学号%.0f", name2, num)
P.S. 综上所述 只是在初学GO时的一些想法,以后会继续精进