So far so good. This is already the third part in this series, and we have already made a lot of progress. The past articles explained how to think in code - by introducing functions. This article will probably be one of the most difficult in this series; here we'll touch something which is almost C-specific: the notion of pointers. C is a programming language which lives close to the assembly language, and in assembly languages you spend most of your time moving data around, but in order to do that you need to know where the data is located, hence its address in memory. And this is just what a pointer is. A pointer is an address in your computer's memory, nothing more, nothing less. But when you're working with C, you'll end up with the conclusion that pointers are everywhere. So, after conquering functions and pointers, we should be able to handle almost anything.

In this article, I will not present a 'fully functional program'. I will present small snippets between the text, but you are encouraged to fire up your editor and start experimenting. You will also see that I introduce some 'extras' which are not mentioned in the main title. I will, for example, also introduce structures, arrays, strings, … , because I want to see this series evolve into a practical tutorial, and not into a C textbook.

Two operators * and &

When handling pointers, you will encounter two 'extra' operators. These are * and &. It helps, when you look at code, that you read * as 'the value stored at this address', and & as 'the address of this variable'.

int anInt=5;
int * anIntPointer=&anInt;
printf("Address: %p Value: %d \n",&anInt, anInt);
printf("Address of pointer: %p Address: %p Value: %d \n",&anIntPointer, anIntPointer, *anIntPointer);
printf("Size of pointer: %d size of int: %d\n", sizeof(anIntPointer), sizeof(anInt));

Thus, we declare an integer and assign this integer the value 5, we declare a pointer (mind the extra *), and we let it point to the address of the previously declared integer. Next, we print the address of the integer, and the value of the integer. Then we print the address of the pointer, the value of the pointer (which is an address, the address of anInt), and the value the pointer points to. And to end, we print the size of the pointers and the size of the integer. This produces the following output:

Address: 0xbfc819d8 Value: 5 
Address of pointer: 0xbfc819d4 Address: 0xbfc819d8 Value: 5 
Size of pointer: 4 size of int: 4 

Here we can see that both pointers and integers are 4 bytes large (which makes sense, since I'm on a 32-bit computer; if you run this on a 64-bit or a 16-bit computer, these values may vary). The address will be different on your system, but the fact that the address of the pointer and the address of the integer are only 4 bytes apart is not a coincidence; they are simply physically stored next to each other. In printf, we use p to print a pointer (in hexadecimal), s to print a string (for more information see man 3 printf). The sizeof() operator used in the printf statement returns the size of an element (in bytes).

Handling arrays

What is an array? An array is simply a list of variables of the same type. In this example, we declare an array of integers where we can store 5 integers. At this point, we also declare how many integers we want to put in there (in this case five). Here we initialize the array at declaration, but we could do it elsewhere in the program as well.

int anIntArray[5]={10,20,30,40,50};
printf("Address of array: %p\n", &anIntArray);
printf("Size of array: %d\n",sizeof(anIntArray));
for(i=0;i<sizeof(anIntArray)/sizeof(int);i++)*{	
printf("Index:%x Address:%p Value:%d Value: %d\n", i, &anIntArray[i], anIntArray[i], *(anIntArray+i));*}

This code produces the following output:

Address of array: 0xbf8b55d4*Size of array: 20*
Index:0 Address:0xbf8b55d4 Value:10 Value: 10 *
Index:1 Address:0xbf8b55d8 Value:20 Value: 20 *
Index:2 Address:0xbf8b55dc Value:30 Value: 30 *
Index:3 Address:0xbf8b55e0 Value:40 Value: 40 *
Index:4 Address:0xbf8b55e4 Value:50 Value: 50

Now, what does this show us? The size of the array equals the number of elements times the size of each element (there is nothing extra stored). All elements are placed next to each other in memory (look at the memory addresses: they each differ by 4. By adding [i] after the array name, we can address an element of the array at index i. But, and here's some magic called 'pointer arithmetic', if we add 1 to an int pointer, the pointer is increased by 4 (the size of the integer) - not by one. So, we can address the array by using the subscript method ([i]), but also with some pointer arithmetic, and, in essence, the array we declared is just a pointer to memory - where several values of the same type are stored.

Назад