When does a pointer variable has its address changed? - pointers

Consider the following example and notice how the location of pointer variable a remains fixed, as expected:
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
Now consider the following struct definition:
type foo struct {
bar int
}
If a is declared as a pointer variable to foo as in this example, its location in memory does not remain fixed.
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
Why is that?

Are you sure you just didn't make a typo and used fmt.Printf("%p\n", a) instead of fmt.Printf("%p\n", &a) because the first one uses &a and your second example uses a.
Long answer:
With
fmt.Printf("%p\n", a)
you're printing out the value of a which is of type *foo which is a pointer. Roughly speaking a pointer is a variable holding an address of a memory location. With
a = &v1
you set a to the address of v1
a = &v2
you set a to the address of v2. v1 and v2 have different locations in memory and thus you when you print the value of a you'll see exactly that.
If you use
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)
then you'll see the same number printed twice because now you're printing out the location of a. So:
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
Remark:
There's some ambiguity as to what people call a pointer and what an address. Some say that a pointer is an address because it contains an "address of a memory location" but a pointer is not actually a memory address depending on the exact context. Also, a points to b usually means that a is a pointer containing the address of b. Likewise, &v is either referred to as "the address of v" and "a pointer to v" which (at least in my opinion) are equally correct which is why I originally used "set a to a pointer to v".

Related

Pointer in func parameter: copy by value or by pointer

here is the code:
package main
import "fmt"
func double(x *int) {
fmt.Printf("pointer of pointer #1: %p\n", &x)
fmt.Printf("pointer#1 : %p\n", x)
*x += *x
x = nil
fmt.Printf("pointer#2 : %p\n", x)
fmt.Printf("pointer of pointer #2: %p\n", &x)
}
func main() {
var a = 3
double(&a)
fmt.Println(a) // 6
fmt.Printf("pointer a in main: %p\n", &a)
p := &a
double(p)
fmt.Println(a, p == nil) // 12 false
fmt.Printf("pointer p in main: %p\n", p)
fmt.Printf("pointer of pointer p in main: %p\n", &p)
}
or in playground.
Question 1: pointer parameters in functions get copy of pointer or get directly pointer?
Question 2: why value x in double function is the same as &a in main func?
Question 3: if x has the same value as &a then why when x = nil &a stil has value and not nil?
Question 1: pointer parameters in functions get copy of pointer or get directly pointer?
The distinction this question is trying to make suggests a certain lack of background understanding.
Think of a pointer as a number / address which can be used to access some other data. A copy of this address just copies a number. Is 42 the same as a "copy of 42"? Yes, in a sense.
x := &value // x holds the address of value now
y := x // and now y does, too
Given the above two lines, assigning x to something else does absolutely nothing to change value or &value. It simply reassigns x to another address. However, doing something like *x = 999 changes value itself because x holds the address of value and the redirection *x means access to value.
If this isn't 100% clear, try to work through the Tour of Go starting here.
Question 2: why value x in double function is the same as &a in main func?
Because of the explanation above. &a is the address of a - it's a number, think 42 again (the real address is something like 0x40e020, but let's call it 42 for simplicity). When you pass it into a function accepting a *int, 42 gets copied and x in double becomes 42. Now both x inside double and &a outside it have the address of a in them.
Question 3: if x has the same value as &a then why when x = nil &a stil has value and not nil?
Because x just has the value 42 in it, which happens to be the address of a. If you assign anything else to x, that doesn't change the address of a, does it? It changes x. x will no longer point to a.

go's big.Int underlying value mutates when value points to another instance

I have come across a bit of unexplained behavior of go's big.Int when pointing an instance of one big.Int to another.
I am knowledgeable that in order to set a value of a bit.Int's instance to another, one must use the Int.SetXXX setters, because they actually cause the underlying abs slice in big.Int to be copied to a newly allocated array. However, putting that aside for a moment, I'd like to know why the following behavior occurs.
Consider the following:
Wrong example (underlying value mutates):
func main() {
v1p := big.NewInt(1)
v2p := big.NewInt(2)
v1 := *v1p
v2 := *v2p
v2 = v1
v1.SetInt64(3)
fmt.Println(v1.Int64(), v2.Int64())
}
(run here: https://play.golang.org/p/WxAbmGdKG9b)
Correct example (value does not mutate):
func main() {
v1p := big.NewInt(1)
v2p := big.NewInt(2)
v1 := *v1p
v2 := *v2p
v2.Set(v1p)
v1.SetInt64(3)
fmt.Println(v1.Int64(), v2.Int64())
}
(run here: https://play.golang.org/p/16qsGhwHIWf)
If I understand correctly, the following should essentially demonstrate what happens in the wrong example:
func main() {
var a, b *int // analogous to the 2 big.Int pointers returned
c, d := 3, 3
a = &c // we set the pointers to point to something we can then dereference
b = &d
e := *a // e and f should now point to the values pointed to by the pointers
f := *b
// the rest is self-explanatory
e = f
c = 5
d = 4
fmt.Println(a, b, c, d, e, f)
}
(run here: https://play.golang.org/p/cx76bnmJhG7)
My only assumption is that somehow when copying the struct content onto v2 in the Wrong example, what happens is that abs slice does not get deep-copied but that the storage that it references is actually the same storage that the slice in v1 points to.
Is this really what happens? Is this the expected behavior according to the language spec too?
As pointed out by icza and Volker, since when dereferencing the big.Int pointer the actual value slice header struct is copied, pointing to the same underlying value, the resulting behavior is that the same underlying array gets referenced from multiple slices, resulting in one altering the other.

Why keys are absent in map

I created a map:
l := make(map[*A]string)
where A is:
type A struct{}
Then added key-values into it:
a1 := &A{}
a2 := &A{}
a3 := &A{}
l[a1] = "a1"
l[a2] = "a2"
l[a3] = "a3"
I expected to see all values ("a1", "a2", "a3") while doing range
for k, v := range l{
fmt.Println(k, v)
}
But I see only the last one.
Why that happens?
https://play.golang.org/p/GSdUWzExxLK
Because your struct has no fields, Go optimizes away all pointers to it to the same address, so you're using the same key every time. Give the struct a field (even if you never put a value in it) and you'll get your expected behavior.
Playground: https://play.golang.org/p/n-WUZ9wqpGJ
You can read more about empty structs (including this pointer behavior) on Dave Cheney's blog.
It's mentioned only briefly in the spec, under Sizes and Alignments, and is in fact the very last sentence in the spec:
A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.
This is because A is an empty structure. As it cannot change go always assigns it the same memory address. If you add a field to A it will start working:
type A struct{a string}
func main() {
a1 := A{}
a2 := A{}
l := make(map[*A]string)
l[&a1] = "a1"
l[&a2] = "a2"
for i, v := range l{
i := i
fmt.Println(&i, v)
}
}
Prints:
0x40e138 a1
0x40e150 a2
https://play.golang.org/p/hYzU73kbVPV
Dave Cheney goes into more depth here:
https://dave.cheney.net/2014/03/25/the-empty-struct

Does dereferencing struct pointer copy the struct?

I have this code:
type countHolder struct {
count int
}
func main() {
a := &countHolder{1}
b := *a
a.count = 2
println(b.count)
}
I expected the output to be 2, but the output was 1.
My understanding was that:
a := &countHolder{1} // a is pointer to struct with data starting at address x
b := *a // b now equals address x
a.count = 2 // the struct stored at address x has its count value changed to 2
Where am I wrong? is b := *a creating a copy of the struct?
From the fine specification:
For an operand x of type T, the address operation &x generates a pointer of type *T to x. [...]
For an operand x of pointer type *T, the pointer indirection *x denotes the variable of type T pointed to by x. [...]
That means that the unary & operator gives you the address of something so a in:
a := &countHolder{1}
is a pointer. The unary * operator in:
b := *a
dereferences the pointer a and leaves you with a countHolder struct on the right side so b is a copy of the struct that a points to. Since b is a copy of the struct, modifying a.count:
a.count = 2
(which could also be written as (*a).count = 2) won't have any affect on b.
You could also have a look at (https://play.golang.org/p/Zubs8qYBA_K):
func main() {
a := &countHolder{1}
b := *a
fmt.Printf("%T\n%T\n", a, b)
}
to have a quick look at what types a and b are (*counterHolder and counterHolder, respectively, in this case).

pointer * and & difference

I am confused on pointers in objective-c. I wrote a very simple program to try and understand
char* temp = "temp";
printf("temp - %s \n", temp);
printf("*temp - %d \n", *temp);
printf("&temp - %s \n", &temp);
printf("&(*temp) - %s \n", &(*temp));
In this example, temp is a pointer to char with a default value of "temp". What does *temp, &temp mean? The output is:
temp - temp
*temp - 116
&temp - 00#
&(*temp) - temp
So temp is the pointer. When I print temp, it prints the value "temp". *temp is the value of the pointer or the address of the variable it points to. What is &temp? Is this the address of the pointer itself?
I wrote a second program in which I assign pointer to address of n (&n).
int n = 50, x;
int *ptr;
ptr = &n;
x = *ptr;
printf("n - %d\n", n);
printf("ptr - %d\n", ptr);
printf("*ptr - %d\n", *ptr);
printf("x - %d\n", x);
The output is:
n - 50
ptr - 2271924
*ptr - 50
x - 50
n is 50 and x is undefined. ptr points to address of n. Why does *ptr print 50 and *temp prints 116? Is the difference between how I have defined the two pointers? I am trying to understand the basics. Thank you.
When we print out *temp, we go to the temp variable, locate the address that it holds (the one it points to), than print out whatever data is in that location.
When we print out &temp, we are asking for the address of the temp variable, not what it is pointing to.
For your second program, you assign the address of n (using &) to ptr. This way, when we choose to call *ptr, it's gonna locate the address stored in ptr (which is n's), and print out whatever n holds. So you then assigned the value *ptr points to, and store it in x.
In summary, when declaring a pointer, & will print out the address of the variable, * will print out what it points to, and nothing in front will print out the address of the variable it's pointing to.

Resources