pointers - Golang &(*(&v)) 语义

标签 pointers go dereference address-operator

我今天遇到了一个问题,能够找到它并快速修复它,但不完全理解为什么 golang 语义是这样的。

我正在使用 Go 1.10。

package main

import "fmt"

type T struct {
    V int
}

var testT = T{}

func main() {
    t := &(*(&testT))
    t.V = 4
    fmt.Println(t, testT) // test.V == t.V -> t == &testT

    t1 := &testT
    t2 := *t1
    t3 := &t2
    t3.V = 5
    fmt.Println(t3, testT) // t3.V == 4 and test.T == 4 -> t3 != &testT
}

输出

&{4} {4}
&{5} {4}

我期望不等于 &testT,因此具有与 t3 相同的语义,但相反,如果我将中间结果存储在变量中,我发现 &(*(&)) 序列没有相同的语义

我的问题

这种行为的原因是什么?

最佳答案

当你这样做时:

t1 := &testT
t2 := *t1
t3 := &t2
t3.V = 5

您获取testT 的地址,将其存储在t1 中。然后在下一行 a new, distinct 变量 t2 被创建,它的内存空间和地址与 t1testT。然后 t3 将存储这个新的、不同的变量的地址,它独立于 t1testT

当你这样做时:

t := &(*(&testT))

你获取 testT 的地址,然后你取消引用指针(你得到 testT “返回”),然后你再次获取这个值的地址,这将是testT 的地址,没有创建新变量。所以 t 将指向 testT

这很正常,合乎逻辑,没有什么奇怪的。规范中的相关部分:Address operators:

For an operand x of pointer type *T, the pointer indirection *x denotes the variable of type T pointed to by x.

所以&testT是变量testT的地址,*(&testT)会返回testT变量。再次获取其地址将与 &testT 相同。

可能暗示反对这一点的是采用复合文字的地址。 Spec: Composite literals:

Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.

当您获取复合文字(例如 &image.Point{})的地址时,它会在底层创建一个新的匿名变量,并且该匿名变量的地址将是表达式的结果。但是获取变量的地址并不会创建新变量。

关于pointers - Golang &(*(&v)) 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49053728/

相关文章:

c++ - 转换指针类型的正确方法

go - 为什么这个分配不是类型不匹配?

c++ - 跳过未使用的虚函数

c - 整数指针作为函数的参数

c - 无法将数组的引用传递给 C 中的方法

go - 在Golang中执行之前如何停止AfterFunc

io - 为什么 io.WriterString 会出现运行时错误?

c++ - 使用 "this"取消引用指针

c - 在一个函数中分配内存并在另一个函数中使用它

c - 为什么这个指针交换在字符串反转中会失败?