Photo by Valentine Tanasovich
For some of us who didn’t start programming with a low high-level language (like C), the idea of “pointers” is alien. It took me a while to fully grasp what “pointers” were when I started learning Go. I understood the concept with Golang first then went back to C and C++ and realised it’s the same stuff!
Here’s my attempt to demystify “pointers”. But before that, let’s talk about addresses.
Addresses: Living Spaces for Code and Data
An address is a reference to a specific memory location. Code and variables are loaded in memory for a processor to work with. For a simple computation like
a + b (assuming
b are integers or whatever operand
+ can operate on in a given language) to be possible. The processor has to know where precisely in memory they are stored so it can pick them and then ADD them; the processor has to know the addresses of these variables.
Pointer: The Neighbourhood Savant
So what is a pointer? Figuratively, a pointer is like the neighbourhood greybeard. He’s the guy that knows everyone in the neighbourhood, where they live, what they do, etc. He’s the guy to go to if you want to know the address of variable
In Golang, a pointer holds the memory address of a value. That’s all it does.
Here’s an example:
In Go, the
& operator generates a pointer to its operand so that
&number becomes a pointer to the variable
&number knows that
number lives at
var addressOfNumber *int = &number is how to declare a pointer variable. An implicit declaration would look like this:
addressOfNumber := &number.
OK. So now we know that pointers hold the addresses of values in memory.
So What’s The Point? (No Pun Intended)
To illustrate the point of pointers, let’s assume you are working somewhere with a wage of $1,500. A new boss comes and asks your junior developer to write a program to double everyone’s payment! It’s all excitement for everyone; you’re elated!
But your developer comes in with this and asks for a code review:
Looking at this, what do you think your new wage will be? $1,500 or $3,000? At a glance, this looks like it’s going to double your wage to $3,000, but it doesn’t! And that’s where pointers come in.
Why We Didn’t Get Our Pay Raise
Our wage from the previous program stayed that same, $1,500. This is because Golang is a pass-by-value language. Pass-by-value is an evaluation strategy, and according to Wikipedia:
In pass by value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function (frequently by copying the value into a new memory region). If the function or procedure can assign values to its parameters, only its local variable is assigned. That is, anything passed into a function call is unchanged in the caller’s scope when the function returns.
So this is what’s happening in our program above:
doubleWage(wage) does its job of double the wage but we do nothing with that doubled value!
The Fight for A Raise
There’s a particular operator we haven’t mentioned…
*. When we use it with a pointer, instead of getting an address of some value, we get a value itself.
We know that
addressOfNumber is a pointer (returns the address of
number), if we did
*addressOfNumber we’d get
33, the value itself. We can go ahead and do something like
*addressOfNumber = 55, and this will set the value of
number to 55; we call this “dereferencing”.
With the newfound knowledge here’s how we can fix our original program to get the pay raise we deserve:
We’ve made our
doubleWage accept a pointer as a parameter and modified whatever the pointer points to with
*wage *= 2. Now to use it, since
doubleWage points to an address we have to pass an address to it with
&wage, and that’s all it takes.
Pointers allow us to jump scope, and this, ladies and gentlemen, is the point of pointers.