We can take this one step further. Not only can we have pointers to simple data types like integers and characters, and more complex data types defined with structs, but we can actually have pointers to other pointers. How do we do that? Recall that the asterisk before the variable name in the declaration means that this variable is a pointer to the specified type. To make this easier to visualize, let's change (insignificantly) where we place the star. If we want to declare a pointer to an integer, we can do it as:

int *steve
but this is the same as
int* steve
The computer doesn't care where we place the *. int *steve is the same as int * steve, which is the same as int* steve.

We can think of the variable steve as having the type int*, in other words, its type is a "pointer to an integer". So if we have the data type int*, how might we declare a pointer to this data type? Just like any other:

int* *steve
steve here is a pointer to a pointer to a integer. The variable steve is now capable of holding the address of a pointer variable, and that pointer variable in turn can hold the address of an integer. Normally, the declaration above would be written as int** steve or int **steve.

We don't have to stop here. We can have pointers to pointers to pointers to pointers, ad infinitum. Go ahead and try it. Start up your favorite C/C++ compiler and try typing in:

int ***steve

The compiler should have no problem understanding that steve is a pointer to a pointer to a pointer to a pointer to a pointer to a pointer to a pointer to an integer. The likelihood that you would need to do this is small, but the occasion might arise.

There is one thing to be cautious about when declaring pointers. The asterisk operator only applies to one variable being declared. For example, in the following code

int* steve, toub, sparknote;
we've actually only declared one pointer, steve. Both toub and sparknote are actually integers, not pointers to integers. To the computer, this actually looks something like:
int (*steve), toub, sparknote
If we want toub and sparknote to be pointers as well, we need to state this explicitly, as in:
int *steve, *toub, *sparknote
For this reason, many programmers prefer placing the asterisk next to the variable to minimize confusion. Placing the asterist next to the type also has its merits. In the end it comes down to a matter of personal style and taste.

I have a pointer... what does it contain?

Notice that we've been careful to say that our pointers can point to a variable of a certain type. The implication is that they don't necessarily point to a variable of that type. In fact when you first declare a pointer, it really can't be used. Why? Because it doesn't point to anything (more accurately it points to a random location in memory, which is extremely unlikely to be usable). A pointer's job in life is to point to another variable by storing its address. How do we get the address of another variable? The answer is the & operator, commonly referred to as the "address-of" operator.