20070627

Pointers for the win

In my last post I used quite a bit of pointer magic to implement a linked list.

If you are not familiar with what pointers are you will have had a hard time understanding the implementation. Let's do something about this, shall we?



image by david ian

Why not use variables only?


A pointer is a way to refer to some data without having to copy it.

That alone may not seem worth the trouble, but there are some (or rather very many) occasions when it is easier to point at the same variable from other places of your code than it is to keep two values in sync.

It may help you at first to think about pointers as meta-variables, a variable you can asign other variables to.



So why did I use them for the linked lists?


Let's go back to linked lists for a moment:

A linked list is comprised of several list elements.

There are two aspects of linked lists, which would make them very hard to implement without pointers:


  1. The first element is not the list, but when you refer to the list, you need to refer to the first element, which in turn lets you iterate through the rest.

  2. Elements don't contain each other, rather they point the user at the next element in line.




Have I seen pointers before?


Chances are you have used pointers before without realizing it. For example, in C arrays are simply pointers, which are automatically dereferenced when you refer to an element inside the array.


Another area you will have come across are strings. You may have learned that a string in C has the type char* or something. Actually, all char* means is a pointer to a character. The string handling functions are smart enough to search the memory at the position the pointer points to for more characters. To mark the end of a string, C uses the zero-termination, ie the last character of a string is always a '\0'.

If you are just starting out ignore this implementation detail. But remember you can impress your friends by dropping that pointers are old hat and that you use them every day.



What is the syntax?


Certainly by now - with all these exciting opportunities stretching out before you - you can't bear the suspence any longer and want to know how you can use this amazing power at your finger tips:

To create a pointer, you do exactly the same as you would when declaring a variable. Except you prefix the name with an asterisk *:

    int *pointer;


And to point to another variable you assign the variable to the pointer, except you prefix its name with an ampersand &:

    int value = 42;
pointer = &value;


And that's pretty much all there is to basic usage of pointers already. Maybe you'd also like to know what the variable you are pointing at contains? Get that by prefixing the pointer with an asterisk * again. Note that this time we are not declaring the pointer, although the prefix is the same:

    printf("the value of the pointer is %d\n", *pointer);



Example


Maybe you have noticed that when you assign to a variable from inside a function its value is not changed when your function returns. This happens by design so the rest of the program is shielded from changes by one function.

But what do you do, when you want to change a variable inside a function which calls another?

Well, you could make the variable public of course, but that would allow every other function to change its value as well. The answer is - you guessed it - use a pointer!

A pointer is really just the address of a variable in memory (you can see this address when you do a printf("the address of pointer is 0x%x\n", pointer);. Of course you very rarely want to know this address!). So you can pass a pointer and write to the address in memory where it actually lies. This happens to be inside the space of the calling function, which is why changes to the value of the pointer affect the value of the variable inside the calling function.

That's a mouthful, so let me illustrate with an example:

#include <stdio.h>

void set_to_five(int *variable)
{
printf("changing value from %d to 5\n", *variable);
*variable = 5;
}

int main(int argc, char *argv[])
{
int myvar = 3;
printf("myvar = %d\n", myvar);
set_to_five(&myvar);
printf("myvar = %d\n", myvar);

return 0;
}



Yeah, this may seem confusing at first, because of all the * and & and the other *. Make yourself clear what happens in the above example and you have understood pointers.

Good luck and have fun!

No comments: