指针变量何时更改了其地址?

时间:2018-06-14 06:25:31

标签: pointers go

考虑the following example并注意指针变量a的位置如何保持固定,如预期的那样:

var a *int

v1 := 1
v2 := 2

a = &v1
fmt.Printf("%p\n", &a) // output: 0x1040c128
a = &v2
fmt.Printf("%p\n", &a) // output: 0x1040c128

现在考虑以下结构定义:

type foo struct {
    bar int
}

如果在this example中将a声明为foo的指针变量,则其在内存中的位置保持不变。

var a *foo

v1 := foo{bar: 1}
v2 := foo{bar: 2}

a = &v1
fmt.Printf("%p\n", a) // output: 0x10414020
a = &v2
fmt.Printf("%p\n", a) // output: 0x10414024

为什么?

1 个答案:

答案 0 :(得分:3)

您确定自己没有输入错误并使用fmt.Printf("%p\n", a)代替fmt.Printf("%p\n", &a),因为第一个使用&a,而您的第二个示例使用a

答案很长:

fmt.Printf("%p\n", a)

您打印出a的值,该值是*foo类型的指针。粗略地说,指针是一个包含内存位置地址的变量。与

 a = &v1

您将a设置为v1

的地址
 a = &v2

您将a设置为v2的地址。 v1v2在内存中有不同的位置,因此当你打印出你的值时,你就会看到它。

如果您使用

var a *foo

v1 := foo{bar: 1}
v2 := foo{bar: 2}

a = &v1
fmt.Printf("%p\n", &a)
a = &v2
fmt.Printf("%p\n", &a)

然后你会看到两次打印相同的号码,因为现在你打印出了a的位置。所以:

a = &v
fmt.Printf("%p\n", a) // prints location of v, not location of a

a = &v
fmt.Printf("%p\n", &a) // prints location of a, not location of v

注:

对于人们称之为指针以及地址是什么,存在一些含糊之处。有人说指针是一个地址,因为它包含一个内存位置的地址"但是指针不是实际上一个内存地址,具体取决于确切的上下文。另外,a指向b通常意味着a是包含b地址的指针。同样,&v或者被称为" v"的地址。和"指向v"的指针其中(至少在我看来)是同样正确的,这就是为什么我最初使用"设置一个指向v"的指针。