This is my attempt at demystifying pointers, a very useful concept available in C, C++ and other programming languages that do not lack balls. Java and PHP have references, a similar feature (C++ also has this) but pointers pretty much are the same thing and for some reason pointers seem ancient, complex or downright frightening to some (or, most).
Why I’m writing this is because I feel a lot of tutorials do not explain pointers as well as I’d like them to explain, considering they are useful and not some archaic curiosity from the 1970s. I originally expressed the concern over here. This tutorial, or introduction, is aimed at C and C++ people because Java doesn’t have pointers and because other languages are generally for wussies.
Note: This is a living tutorial, i.e. you can suggest things and I’ll make it better. I’m all for a good pointer tutorial.
What are pointers?
At first, let’s think about computers. A very basic computer has memory for the data and the code. In a programming language, a variable refers to a location in the memory. The location, referred by address, is something like a page number in a book. At the very least, a programming language automatically assigns these memory locations and acts as a directory for the book, allowing you to refer to the locations by the variable name instead of the page number.
In a programming language, pointer is a variable that contains the address. Simple as that. In most cases, a pointer contains an address of another variable. The pointer can then be used to read or change the contents of the referred variable.
How do I use pointers?
In C, using pointers is easy. To make a variable as a pointer to another variable of type A, you define the pointer to be of type A*.
A variable=42;
A* pointer_to_a_variable=&variable;
*pointer_to_a_variable=0;
& can be read as “address of”. * can be read as “contents of”. Try reading the above example like that and you should figure out what it does.
Here is the answer:
A variable=42;
A* pointer_to_a_variable=&variable; // a pointer to the above variable
*pointer_to_a_variable=0; // the contents of the variable referred are zeroed
When should I use pointers?
A pointer can be very useful in a variety of situations. The simplest use would be something like passing a reference to a variable as a function parameter and the function then changes the variable. This is impossible without either references or pointers. At the very far end of the same spectrum, pointers are the only way to implement polymorphism in C++, which is an important and useful concept in object oriented programming.
Using pointers is natural when in a function you need to use the contents of an object given as a parameter and change them. If you don’t pass a pointer or a reference to the object, you will only change the data in the copied object. For example, see the C++ function below.
void func(Object obj) {
obj.data=0;
}
This bit of code would be quite useless, considering the object obj is discarded after the function exits. The data member of the object passed as a parameter will not be modified because the object is duplicated for use in the function. The below function does the same but with the exact same object that was passed as a parameter.
void func(Object& obj) {
obj.data=0;
}
Now the object is not duplicated but obj is a direct reference to the original object. data will be zeroed. Below is yet another version of the same functionality, this time with a pointer.
void func(Object* obj) {
obj->data=0;
}
This does the same thing, only that obj is a pointer to the object. The above examples show how pointers indeed can be avoided by using references or other more modern concepts (and in some languages you are forced do it with references).
However, in C++, the above example (the one with the pointer) would also allow you to pass an object as a parameter that was inherited from the class Object. By using C++ references this is not possible. Now, if the function called a member function, it would call different bits of code depending on the object! This can be a very, very powerful and nice feature. And you can’t do it without pointers (in C++).
Show me more examples.
In C and C++, the line between arrays and pointers is a bit blurred. For example, you can use a pointer as an array, in that you can use an index with an array and a pointer. Below is an example:
int a[2]={123,456};
int* b=a;
a[0]=0;
b[1]=0;
The array a is now full of zeros. Note that b only refers to the array, it doesn’t have its own data. Also note that specifying an index eliminates the asterisk in front of b. This is because in effect b[1] is the same as *(b+1).
Continuing from the above:
int a[2]={123,456};
int* b=a;
a[0]=0;
b=b+1;
*b=0;
This also zeros the array, because the pointer b is incremented. A pointer is simply a variable with an address and you of course can change that value. This is called pointer arithmetic. It can be very helpful and actually will often allow faster code: using an index needs a multiplication while smartly incrementing pointers only needs an addition (your mileage may vary — compilers are getting better and better). See the below example:
int a[100];
int i;
for (i=0;i<100;i++) a[i]=0;
The below modification should be marginally faster.
int a[100];
int *ptr=a;
int i;
for (i=0;i<100;i++) { *ptr=0; ++ptr; }
This is because in effect, the below example only increments the pointer while the above calculates the address using index.
Note: Many younger coders suffer of premature optimization. This is not a permanent condition and will reduce with some experience. The above is not a good place to optimize (what computer can’t do that fast enough for 100 times?) but do keep that trick in mind. At the very least, it can make code a bit shorter.
Afterword
This is it for now, I can’t think of anything more about basic pointer use. Honestly, it is a bit hard to imagine things from the perspective of an absolute beginner. Any ideas are welcome.