The memory address of a variable
A variable is a space in the memory of the computer that stores information. It therefore has an address (Position in bytes relatively to the start of the memory) and a size (In bytes). The address of a variable is the address of its first byte.
Retrieving the address of variable
We can retrieve the address of a variable by putting an ampersand & before its name:
int var; &var; // The result is the address of the variable var. However, we do nothing with it here.
What is a pointer?
A pointer is a variable that stores a memory address (Of a variable). We can then use the pointer to access the variable located at that memory address.
Defining a pointer
To define a pointer, we must add, in its definition, an asterisk * between the variable type and the variable name.
float * pointer; //Defines a pointer of type “float”.
Setting a pointer
To set the value of a pointer with the address of a variable (Make it point to a variable), we must simply assign the pointer with the address of the variable:
int var = 4; int * varPointer = &var;
Note that the type of the pointer must be the same as the type of the variable.
Accessing the variable pointed by a pointer
We can access the variable pointed by a pointer by placing an asterisk * before the pointer name.
float var; float * varPointer = &var; *varPointer = 5; // var now equals 5.
It is also possible to access the pointed variable by adding  after the pointer:
varPointer = 9; // Now, var equals 9.
A number between brackets following a variable of pointer type basically means: access the variable, from the address pointed by the pointer, at the index specified between the brackets.
Let us consider that there is, in the memory, an other variable of type int directly following var. Then, it would be possible to access it by putting 1 in the brackets:
varPointer = 9;
If there is an other variable of type int after it, we could put the number 2 between the brackets to access it and so on.
Instead of using brackets, we can instead add numbers to the pointers. Adding 1 to a pointer has the effect of returning the address of the variable following the one currently pointed. A pointer is a variable that stores an address, so an address is a pointer. We must then use the asterisk to access the pointed element.
For example, this:
*(varPointer+1) = 2.5;
Is equivalent to:
varPointer = 2.5;
Let us say we defined a pointer of type int which points to the address 1000. If the type int weights 4 bytes, then, adding 1 to the pointer will return the address 1004 (The address of the variable following, in the memory, the variable of type int at the address 1000).
However, when we access a variable through a pointer, we must be sure that there really is a variable there, otherwise, we could access (And change) something we are not supposed to (And likely make the program crash). We will get into that soon.
Note that accessing the variable pointed by a pointer is called dereferencing the pointer.
Copying a pointer
If the pointer pointer points to the variable, of type int, var, then the following:
int * pointer2 = pointer;
Makes pointer2 point to var too.
A pointer is a variable that stores an address in the computer memory (A number), therefore its value is the address of the variable it points to.
The address zero
The first byte in the memory of the computer (RAM) has the address 1. That means that zero is not a valid memory address. Therefore, pointers that are not currently used are often assigned with the value 0. That way, if by mistake we try to set the value of the bytes at the address pointed by the pointer, we will not change the value of something we are not suppose to touch. Also, it makes it easy to test if the pointer currently points to something (If its value is 0, it does not). By the way, programs have sections of the memory assigned to them (It is actually a bit more complex than that, but that is enough for now). If they try to read or write from/to a memory address that does not belong to them, they will crash (Be terminated by the operating system).
Pointer of pointer
In order to define a pointer of pointer, we must put, when we define the it, 2 asterisks ** instead of 1 *. If we want to define a pointer to a pointer of a pointer, then we must put 3 *** asterisks and so on.
int var = 1; int * ptr = &var; int ** ptr2 = &ptr;
To access ptr from ptr2 (And set its value to 0) we can do the following:
*ptr2 = 0;
ptr2 = 0;
We can access var from ptr2 (And set its value to 0) like that:
**ptr2 = 0;
It is also possible to access var like that:
ptr2 = 0;
NULL and nullptr
To make pointers point to an invalid memory address, instead of assigning them with the value 0, we can use the keyword NULL, from the language C, or the keyword nullptr, from the version C++11 of the language C++.
int *ptr1 = 0; int *ptr2 = nullptr; int *ptr3 = NULL;
Using those keywords, even though they are less concise than simply writing 0, comes with the advantage that it makes it more explicit (To people reading the code) that we are assigning an invalid memory address to the pointers rather than the number zero.
Note, however, that the numerical value of nullptr and NULL is 0.