C++ Tutorial for noobs - Part 12: Pointers
...Back to Part 11: Type-Conversions
Motivation
Finally, the almighty pointers. If you never heard about pointers before, this part of our C++ tutorial series will change how you think about computer programming forever.
"This is your last chance. After this, there is no turning back. You take the blue pill - the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill - you stay in Wonderland and I show you how deep the rabbit-hole goes."
- Morpheus
This tutorial will explain how variables and arrays are stored in memory, how we can get their memory address (also known as pointer) and how we can read out the content of that address.
Understanding Memory
To understand pointers, we have to understand our computer's memory first. Now don't worry, we won't talk about the really weird stuff. We will just try to understand where our variables are located.
Let's say we have a C++ int variable with the value 42:
int i = 42;
Our computer has a certain amount of memory, also known as RAM. Now there are only two things that we have to understand:
- Our Variables are all somewhere in that memory.
- Each of them is really just a memory address.
If we have Gigabytes of RAM, we somehow have to make sure that we can find our variables in there - therefore they all have an address, or to be exact: they are the address.
Variables in Memory
Here is what really happens if we create a int variable with the value 42:
MEMORY_AT_00489710 = 42;
Which means that the value 42 is stored in the memory address 00489710.
Note: it's not always the same address.
Arrays in Memory
If we create a int array of size 3 with the values 0, 1 and 2 then this is what really happens:
MEMORY_AT_00489720 = 0;
MEMORY_AT_00489724 = 1;
MEMORY_AT_00489728 = 2;
Or in other words: the computer just puts all three values one after another into memory.
Names are Awesome
And because it's kinda weird to remember all those addresses, C++ allows us to give them names like i or myVariable instead.
Bytes, Bytes, Bytes
Okay we know that our computer memory is basically just a whole bunch of addresses and we know that there can be values saved at those addresses.
Modern computers have several Gigabytes of memory, so we kinda have to know how many bytes our typical variable needs.
Here is the answer:
- int needs 4 bytes
- float needs 4 bytes
This means that if we want to store several int variables in memory, they would be four bytes apart from each other, because each of them is 4 bytes huge.
Finding out the Address
Variable Address
If we have a variable, we can find its memory address really easily by using &:
int i = 42;
std::cout << &i; // gives something like 0042FE98
The above code gives us a number like 0042FE98. Don't worry if you get a different number, this is totally normal because you also use a different computer.
We can store the memory address of a variable in a new variable like this:
int i = 42;
int* p = &i;
This is also known as pointer.
Array Address
As mentioned before, an array of size 3 means that there are three values next to each other in the computer's memory.
If we want to find out the address of the first, second and third value, the logical thing would be this:
- The Array itself is always the first address already
- Find out the second address by adding 4 to the first address, because the next int value is obviously 4 bytes further away
- Find out the third address by adding 8 to the first address, because the third int value is then 4 + 4 = 8 bytes away
The good (or bad?) news is that C++ is trying to be extra smart so we don't have to worry about the size of our variables (4 in case of int). C++ calculates the variable size itself, so all we have to do is this:
int arr[3] = {0, 1, 2};
std::cout << arr << "\n"; // address of the value 0
std::cout << arr+1 << "\n"; // address of the value 1
std::cout << arr+2 << "\n"; // address of the value 2
Explanation:
- The Array is always automatically the address of the first value
- If we use that address +1 then C++ gives us the address of the next int value (which is + 1*4)
- If we use that address +2 then C++ gives us the address of the next int value (which is + 2*4)
Reading the Address Content
Okay, now let's get to the really fun stuff. If we know a variable's memory address then we can also read its content any time.
For example, here is how we create a int variable, get its address and read out the content of the address:
int i = 42;
int* p = &i; // is something like 0045FA48
std::cout << *p << "\n"; // gives 42
This gives out the number 42 because we just got the address of i and then read out what's in that address, which is 42.
Okay, let's do the same with our array arr:
int arr[3] = {0, 1, 2};
std::cout << *arr << "\n"; // gives 0
std::cout << *(arr+1) << "\n"; // gives 1
std::cout << *(arr+2) << "\n"; // gives 2
We simply calculated all three memory addresses (with +1 and +2) and then read out the content of those addresses by putting a * in front of it.
Summary
The goal of this tutorial was to gain a basic overview about how to use C++ pointers while providing a few useful examples.
Pointers are one of the main reasons why people decide to use C++ in their projects. They are really useful in a lot of things like complicated (yet interesting) tricks to save performance or even when developing drivers or doing operating system related stuff.
Feel free to play around with the above examples to get a feeling for the whole pointer thing, it will sure benefit you later on.