指向不同内存位置但更新相同变量的指针

Go Pointers pointing to different memory locations but updating same variable

总结: a 指向分配给 b 的内存地址 0x40e020c,然后分配给 b 的内存位置(或者我认为)。当我打印出 c &c 的地址时,它指向内存中的另一个位置 0x40c138.

package main

import (
    "fmt"
)

func main() {
    var a int = 42
    b := &a
    c := b
    *c = 4

    fmt.Println(a, b, &c) // output --> 4 0x40e020 0x40c138

}

问题:指针c如何更新a的值?我希望 a 打印出 42,但编译器吐出 4.

c 打印 a 的内存地址。 b 是保存 a 的内存地址的变量,c 是 b(这些变量保存相同的值)。 当您打印 &c 时,您打印的是保存 a 的内存地址的变量 c 的内存地址。 您可以使用 c 更新 a 的值的原因是因为 * 运算符允许您访问或跟踪 c 保存的内存地址并更新它保存的值。

让我们详细分析一下这里发生的事情:

var a int = 42
b := &a
c := b

您现在拥有三个变量,每个变量在内存中都有自己的位置。 a 是一个整数,值为 42bc的值相同,都是a的内存地址。

*c = 4

这将取消引用指针 c 并将值 4 写入它指向的内存位置,即 a 的内存位置。这就是为什么在打印 a 时您会看到值 4 - 此行会覆盖 a 的内存位置中的值。这是指针的主要目的 - 允许多次引用内存中的相同值。

fmt.Println(a, b, &c) // output --> 4 0x40e020 0x40c138

这会打印出a的值,b的值(即a的地址),以及c的地址。

一张图片可能会有所帮助。这是您计算机中的(部分)内存,从 0x40c138 到 0x40e020 左右:

           +---------+                            +---------+
 ????????: |    *    | (variable "b")   0x40c138: |    *    | (variable "c")
           +----|----+                            +----|----+
                v      ________________________________/
           +---------+'
 0x40e020: |    4    | (variable "a")
           +---------+

变量bc都指向变量a。您打印变量 bvalue,即 0x40e020,这是我们知道 a 本身在内存中的位置的方式。您打印变量 c 地址 ,这就是我们知道 c 本身在内存中的位置的方式。你没有打印变量 b 的地址,所以我们不确定它在哪里,但我们知道 bc 都指向 a,所以我们可以画出每个箭头出来的箭头。

由于从 c 出来的箭头指向 a,因此通过 *c 写入会写入 a