pointersgodereferenceaddress-operator

Golang &(*(&v)) semantic


I faced an issue today and was able to find it and fix it quickly but do not fully understand why golang semantic is like that.

I'm using 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
}

Output

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

I was expecting not to be equals to &testT so have the same semantics as with t3, but instead I see that &(*(&)) sequence do not have the same semantic if I store intermediary results in variables

My question

What is the reason for that behaviour?


Solution

  • When you do this:

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

    You take the address of testT, store it in t1. Then in the next line a new, distinct variable t2 is created which will have a different memory space and address than that of t1 or testT. Then t3 will store the address of this new, distinct variable, which is independent of t1 or testT.

    When you do this:

    t := &(*(&testT))
    

    You take the address of testT, then you dereference the pointer (you get testT "back"), then you again take the address of this value which will be the address of testT, there is no new variable created. So t will point to testT.

    This is normal and logical, nothing surprising is in it. Relevant section from the spec: Address operators:

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

    So &testT is the address of the variable testT, and *(&testT) will give you back the testT variable. Taking its address again will be identical to &testT.

    What may hint against this is taking the address of a composite literal. Spec: Composite literals:

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

    When you take the address of a composite literal (e.g. &image.Point{}), that does create a new, anonymous variable under the hood, and the address of that anonymous variable will be the result of the expression. But taking the address of a variable does not create a new variable.