home

Tutorial index

C Tutorial V: Pointers and Arrays

So you think you got the hang of it and can now go and make what made you look at these tutorials in the first place? You’re not quite done! There are important concepts and practices still to learn. In the previous tutorial I said I’d introduce you to pointers and arrays. To clear it up, if you didn’t pick this piece of information up during the other tutorials, an array is a pack on variables. It is symbolized with it’s name and the number of the variable in brackets next to the name: name[number]. Thus name[i] is the i-th variable in the array. You have to keep in mind that i-th also includes the 0-th variable, since in programming we start at 0. That’s the entire basis of arrays, some teach them before even teaching math, but I decided you didn’t need them just yet, and decided to teach them in more depth in this fifth tutorial. You can go ahead and declare an array and use it as I just described, and I’m not going to say you should read through because this is enough for using them.

However in depth, an array is a pointer to a memory address, and the variables of the array are in consequent addresses. A pointer is a variable-ish thing that points to a memory address. Think of it as such: your x variable is stored in address 0x0100, and you have a pointer called xp, if xp points to x, xp contains the address 0x0100, and when we use xp, we are redirected there. What’s the point to all this though? Let’s also assume a variable y, at 0x0200. If I were to say that x is my target, I would perform all operations on x, but were I to switch target to y, I would need the same code re-written with y in the place of x. Imagine that when there are fifty targets, you can’t write so much code. Instead you can perform all your operations on xp, and change the place where xp points to instead. You can even make the changing process one line for all your possible targets if you use your skills well. Keep this in mind, it will be useful in the future.

I mentioned before that an array’s variables are in a row, consequent. This is why an array is essentially a pointer. The first element or the array array[] is array[0] (start counting from 0, remember?), and if it is in 0x0100 and it is of type int, it is safe to assume it covers the area up to 0x0103, that is, it is 4 bytes long. The second element starts right after that, at 0x0104, ending at 0x0107. The third at 0x0108, and the fourth at 0x0112. Notice a pattern? Each n-th element is at 0x0100 + n * sizeof(int). Of course it is not size of int in a float array, but you get the idea. So all you need for an array is a pointer to the first element and the type of it’s elements, so when you say array[x] you actually say &array[0]+sizeof(array_type)*x. Take a moment and put it on paper, and remember that the ampersand gives us the address. Do the math, it’s pretty clear once you understand the operands in the equation.

Now you can see why I teach arrays along with pointers. So you saw how the array works, what use is this? We’ll get to that point. A pointer has of course it’s own address, it has to keep the address it points to somewhere after all, and pointers generally have a set size, rather small. The thing is that you can use them for what they point to, done by putting an asterisk in front of the pointer’s name (this gives us the object that is pointed by the pointer, it’s content, it’s value), but also to get to what they point to, to get it’s address. Remember how I said arrays in printf() do not need the ampersand? It is because a pointer is an address essentially. Typing it’s name alone gives us the address of what we point to, so we can use the pointer without the ampersand to scanf() a value to the pointed object. However weird things happen, which allow you to place an ampersand before the pointer.

With an ampersand and the pointer’s name you have the address of the pointer, the address of the thing that stores the address of the pointed object, the address in which the pointed object’s address is stored, a pointer to a pointer. It is getting weird, huh? To get a better grasp of this you should go back to when we were saying that an array is a pointer. Remember I said we can have multi-dimensional arrays? Think of a 2 dimensional array as an array of single dimension arrays. A two dimensional array is a square, a three dimensional array is a cube; imagine the elements of each of these as smaller cubes. This way you can say you have an array of lines of cubes, and an array of arrays of lines of cubes respectively.

The second level array, the array of arrays, is a pointer to an array, a pointer to a pointer. To be absolutely honest, when you use multi-dimensional arrays, C doesn’t do it exactly like this, but if you are to become a good manipulator of arrays you will do it this way, as this works with absolute precision.

So I guess –and hope, and pray- that you understood this more or less. So for those patient enough to keep on reading, I award you with the knowledge that if you declare an array you have to tell C how many elements there are in it, so you predefine how many components it can hold. However an array is a pointer with some memory allocated to it, thus one can convert a pointer to an array. This allows us to allocate the memory based on user input or other calculations, which adds flexibility. To allocate memory to a pointer we use malloc() (memory + allocation). This function’s argument is the size of memory to be allocated in bytes. Usually we use sizeof() and multiply it by the number of elements we want in our array, this process can be done at any point in runtime, giving us flexibility. The example bellow illustrates how this is done.


int *arrayPt;
int x;
scanf(“%d”, &x);
arrayPt = malloc(x* sizeof(int));

This piece of code lets the user define how many elements to put in the array. X should be stored and used in the future, unless you want to be finding out how long the array is. This however can be useful when writing your own functions, as they become equally versatile and can support multiple array sizes, it is done by dividing the sizeof() of the array with that of it’s type:


int size = sizeof(arrayPt)/sizeof(int);

Arrays created as pointers are accessed either as the name of the pointer + the number of the element you want to access, or as you would in a regularly declared array, with the name of the array and the number in brackets.This enables you to only use pointer code once for creating, and possibly once more for expanding arrays, and proper array code for the rest of the program.

Another interesting point is that you can have two pointers, so that when you want to expand an array, you can allocate memory to the second one, pass the array to it, then reallocate larger memory to the first one and copy it back, having extra cells (positions in the array, room for data). This allows for dynamic arrays, not only static ones, and by expansion, this qualifies as dynamic memory allocation, DMA, a term used for describing the allocation of memory according to your needs. However remember to free() the memory allocated to each array after copying it’s contents.

Finally, arrays are called parallel when consecutive cells are referring to consecutive objects, this doesn’t mean anything to the code, but for you it’s like saying that the first cell of each array refers to the first unit, the second to the second unit, the n-th to the n-th and so on, so you can have multiple variables stored for multiple units in multiple arrays without loosing track.

Take a look at these examples to see if you get it, and try to use them afterwards on your own! There will also be a bonus tutorial on more advanced topics such as linked lists and other complex structures after the structures lesson.

What now? Well, you might not be able to think of something that can use this knowledge, but I’ll give you an idea. Try a trading game, where the player travels through x villages, buying and selling goods. You will need parallel arrays, one for the villages gold, and three for each resource, one for the stock, one for it’s growth, and one for it’s price. Make growth of variable size and cook up a formula to determine the price, you can even skip the price array if you move into the next lesson –which is easier by the way. Another idea is to have a two-player game, and create an array of 2 arrays. An extra pointer will be used to access the variables inside, and when players change turns you will only change that pointer so that it points to the other player’s array. This can be done with two separate arrays, a pointer-to-pointer array or any way you like, you’re the boss here.

I cannot make a general statement on what you can now make, but the general idea is that now you can manage a larger amount of different characters, units etc without being very specific with numbers. Try it out, find a good way to use it, find out how this all works, experiment and have fun! In the next lesson we talk about functions and how they make life easier and code tidier.

Notice how although some thing are taught much earlier in other tutorials, I try to teach them so I do not have to go backwards and tell you how to make old knowledge compatible. I am trying to make tutorials straight forward, without need for looking back and changing knowledge on already known facts. I hope I am achieving this, after all I do not risk having to change earlier tutorials, or relying on something I believe I have already mentioned.