The & operator takes a variable and gives back its address. So for example, if we have a variable int steve, the expression &steve is the address of steve. This address can be stored in a pointer.
The address stored in the pointer is like any other value in a variable. We can assign it to another variable:
Using the information in a pointer
Now that we have the ability to create pointers and to put addresses into them, what can we do with them? Remember that a pointer's job in life is to hold the address of a location in memory. Wouldn't it be great if we could then take that address and find out what it contains? Well we can; that's the whole idea.
To find out what the memory at an address holds, we use the * operator. As we've seen, the * operator has multiple meanings in C. It can be the multiplication operator. It can be used to declare a pointer. It can also be used to dereference a pointer.
Dereference? Yes. To dereference a pointer means to take the address contained in the pointer variable, and go find whatever data resides at that address. You might find it helpful to think of an analogy. Think of the phone book as a huge array of pointers. Each entry in the phonebook contains the address of a person's house. To find out who lives in that house, you get in your car, drive over there, knock on the door, and see who answers. That process of driving to the persons house and seeing who was inside is like dereferencing a pointer.
To dereference a pointer, we use the asterisk. By putting the asterisk operator in front of a pointer, we're telling the computer to go fetch the memory addressed by that pointer.
Something to be very careful of here. When you first declare a pointer, as mentioned above, it doesn't point to anything meaningful; like all variables when they are first declared, it contains garbage. When you declare a variable, the computer goes and sees what memory it has available and then assigns your program a small chunk of it for the variable. However, it doesn't clear out the memory at that location. Whatever was in that memory location before you were given the right to it is still there. This can lead to trouble if you're not careful.
Look at the following code:
Now that we've seen the dereferencing operator, the declaration of pointers might make a little more sense. Instead of thinking of int *ptr as a pointer to an integer, we can imagine that "*ptris an integer". Of course, this method of thinking about pointers has some drawbacks, mostly linked with the memory problem described above. When you first declare int *ptr, it most likely doesn't point to anything valid, but if you think of int *ptr as declaring *ptr as an integer, you might think you can use it just like any other integer. Unfortunately you can't because, again, it most likely doesn't point to anything legal.
Pointers to structures: the -> operator
Let's say we have the following code:
Remember that with structures (and classes in C++) we use the . operator to get at the fields contained within the complex type. So for example, to access the steve variable's age field we would write steve.age. We can do the same thing with the *ptr, for example (*ptr).age. Why, you might be asking, do I have those parentheses there? The answer is that the . operator binds tighter than the * operator, meaning that this is equivalent to *(ptr.age). The computer will first try to get the age field of the ptr variable, and then attempt to dereference it. As such, we need to put in the parenthesis ourselves to force the computer to do what we want.
This can get tedious, especially considering the frequency with which pointers and structures are used in combination. To make our lives easier, C provides another operator, the -> operator, which can be thought of as the "dereference this pointer and get a specific field" operator. Instead of writing (*ptr).age, we can just write ptr->age.
Pointing to... NOTHING
Often it is useful to have special values to indicate that a variable is not valid. For pointers, C/C++ gives us a special value to use, the NULL value, that says just that. Programmers use the value NULL to signify that a pointer does not contain a valid address, that it doesn't point to anything useful. A particularly useful feature of NULL is that it's guaranteed to be interpreted as "false" in if constructs:
All the basic tools
You now possess all of the basic basic knowledge needed to use pointers. However, why we'd want to use pointers may still seem a mystery. As you progress through the following sections of this guide, you'll see how useful pointers really are.