When it comes to pointers many people say that they are a big advantage of C++. If you ask me that’s not entirely true as pointers may also add a lot of complexity to your code and, therefore, require special care! Especially when it comes to pointer arithmetic and pointer manipulation it gets very complicated quickly, e.g. a very common use of pointers is to iterate over an array:

int numbers[5] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 5; i++) {
    std::cout << "Number " << i << ": " << *(numbers+i) << std::endl;
}

This will print out all the numbers of the array. And just to mention it – this is equivalent to:

int numbers[5] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 5; i++) {
    std::cout << "Number " << i << ": " << numbers[i] << std::endl;
}

It turns out that the array-operator [] performs the pointer arithmetic and the dereferencing under the hood and simply "looks nicer".

While this example may look straight-forward to you, how about the next one?

int* a = new int(33554432);
int** b = &a;

**b++;   // 1) changes the value of a?
**(b++); // 2) changes the value of a?
*(*b++); // 3) changes the value of a?
*(*b)++; // 4) changes the value of a?
(**b)++; // 5) changes the value of a?

Okay, why would somebody do something like that? Well, a very common practice is to use pointers to pointers in methods to let the caller decide where to store the calculated data of the method. Don't ask me why this pattern has become so popular... Probably they just didn't know better some years ago (or they wanted to make sure nobody will get their jobs later ;-) ).

Anyways what's the solution to the example above? Which statement actually changes the value of a? Let's look at the statements one-by-one:

The statements 1, 2 and 3 do not change the value of a but they change the location b points to! Statements 1, 2 and 3 are equivalent which is a result of how C++ binds the operators. In these cases the pointer location gets incremented by 8 bits, but this number depends on the size of a pointer (32bit / 64bit machine). If we are unlucky we end up pointing to somewhere ... let's say not pointing to a anymore! So you do not want to use that arithmetic at all!

Statement 4 increments the pointer of a, meaning the address variable a points to, but not actually the value of a. You can use this arithmetic if a was an array and you need to iterate of the array that was given by the address b. This is a very useful case even though I would recommend you do not to fool other people by reading these lines of code! You could simply hand in a copy of the reference pointing to the array instead, which makes it much more easier to read!

Statement 5 finally changes the value of a and if a was an array of ints it would change the value of the first element of the array.

As you can see pointers can easily confuse the readers of your code (and you are also a reader of your own code!). I don't say that you should not use them to tweak up your programs but I advice you to take care of your pointers. Better think twice before using pointers in such ways...