Golang&(*(& v))语义

时间:2018-03-01 15:59:12

标签: 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相同的语义,但我发现&(*(&))序列没有相同的语义,如果我存储中间结果变量

我的问题

这种行为的原因是什么?

1 个答案:

答案 0 :(得分:9)

执行此操作时:

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

您获取testT的地址,将其存储在t1中。然后在下一行 a new 中创建 distinct 变量t2,它将具有与{{1}不同的内存空间和地址}或t1 。然后testT将存储此新的不同变量的地址,该变量独立于t3t1

执行此操作时:

testT

你取t := &(*(&testT)) 的地址,然后取消引用指针(你得到testT“返回”),然后你再次取这个值的地址,这个地址将是{{1 },没有创建新变量。因此testT将指向testT

这是正常和合乎逻辑的,没有什么令人惊讶的。规范中的相关部分:Address operators:

  

对于指针类型t的操作数testT,指针间接x表示*T指向的*x类型的variable

因此T是变量x的地址,而&testT会返回testT变量。再次获取其地址将与*(&testT)相同。

可能暗示这是一个复合文字的地址。 Spec: Composite literals:

  复合文字的

Taking the address生成一个指向使用文字值初始化的唯一variable的指针。

当您获取复合文字的地址(例如testT)时,确实会创建一个新的匿名变量,该匿名变量的地址将是表达式的结果。但是获取变量的地址不会创建新变量。