变量 & 地址 & 指针 & 实参 & 形参(一)

94 阅读2分钟

变量 & 地址 & 指针

变量名相对于地址来说,更像是地址的别名。

在声明变量的时候,系统在内存中划分一片地址,并把这片地址命名为<变量名>,

而对变量的赋值, 则是在地址中存入内容, 这个内容常被叫做字面量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
*/

可见实参和形参是完全不一样的两块地址


  1. 交换变量

    所以说由以上,在交换变量的时候,我们只传给实参的变量是没有用的,因为对形参的内容变化 无法返回给实参,形参在函数结束之后就消失了。那只能将传要变换的变量的地址,将地址传给形参进行操作,对地址的影响会影响到世纪我们想要改变的变量

    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
    }
    

    只有这样,才能实现交换两个变量的值,而直接传变量值是实现不了实参的交换,只能实现形参的交换。

  2. 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时的一些想法,以后会继续精进