Skip over navigation

Contents

What Are Pointers?

Pointers and Arrays

Problems

Problems

They're the same!

Ok, that's not exactly true. Pointers and arrays are not exactly the same entity, but they're very close. In fact, an array is for all intents and purposes a constant pointer.

What?! How can an array be a pointer, and how can a pointer be an array? Before we delve into that question, we first need to discuss pointer arithmetic.

Pointer arithmetic

If you have an integer variable, you can add the number 1 to it and the contents f that variable will increase by 1. You could add an 'a' to a character variable and it would increase by the value 'a'. With pointers, arithmetic is also possible, but a little quirky. Once we understand how pointer arithmetic works, however, it is an invaluable aid. In fact, as we'll see, arrays work properly because of pointer arithmetic.

As we've seen, pointers store an address in memory. If we have an integer pointer, it points to a memory location that can hold an integer. If we have a character pointer, it points to an address in memory that can hold a character. And so forth. So all a pointer really holds is a big number, say, for example, 0x4b14 (or in binary 0b0100101100010100). We might expect that if we added a number to this, say the number 1, that the pointer would then hold the number 0x4b15. Fortunately, that is not always the case.

When you add numbers to pointers, the address stored in the pointer isn't necessarily increased by that many bytes. That would cause trouble, for example, with an integer pointer. Let's say we had a series of integers in a row located at addresses 0x4b14, 0x4b18, 0x4b1b, and 0x4b1f (remember that integers on most modern machines, and the example machine we're dealing with here, are a 4-byte data type, meaning they take up 4 bytes). Let's say that we have a pointer ptr that currently holds the address 0x4b14. If we executed the instruction: ptr = ptr + 1; without special arithmetic, if ptr were just an integer variable, we would end up with the value 0x4b15. But this number doesn't make any sense in terms of memory addresses. A single integer resides at the memory addresses 0x4b14 through 0x4b17, so accessing the memory at address 0x4b15 would be accessing into the middle of an integer. Fortunately, this is not how pointer arithmetic works.

When you add a number to a pointer, the computer knows what type of data the pointer points to, and multiplies the number you're adding by the size of the pointer's type before adding it to the pointer. For example, taking the case from above, if we have the following code:


ptr = ptr + 2
and if ptr is a pointer to an integer and originally contained the value 0x4b14, then the computer really does the math: ptr = 0x4b14 + 4*2 = 0x4b1c meaning that it adds 4 bytes to the pointer for every 1 unit being added. If we were dealing with a character, normally a one byte data structure, then the math would be: ptr = 0x4b14 + 1*2 = 0x4b16 and if we were dealing with some big data structure that took up 200 bytes for every structure, then the math would be: ptr = 0x4b14 + 200*2 = 0x4ca4

Figure %: Adding 1 to an integer pointer

Another possible way to do pointer arithmetic is to subtract one pointer from another. Again, let's go back to the example where we have the four integers in a row at addresses 0x4b14, 0x4b18, 0x4b1b, and 0x4b1f. Let's say we have four pointers, ptr1, ptr2, ptr3, and ptr4, each pointing at the addresses in order. With normal arithmetic, ptr4 - ptr1 would result in the number 12 meaning that there are twelve bytes between them. However, with pointer arithmetic the computer takes into account the size of the data type involved, in this case an int. As such, ptr4 - ptr1 actually results in the value 3, meaning that the two values are separated by 3 integers.

Figure %: Subtracting integer pointers: ptr1 - ptr2 == 2

Enough stalling. What do you mean they're the same?

In the C/C++ language, pointers and arrays are closely related. As it turns out, an array is just a series of variables laid out in a sequence, one after the other. If you were to declare an array of four integers, you would end up with a situation very similar to the one described above.

Figure %: An array of three characters, arr

As a starting example, let's declare a few variables:


int arr[4];
int *ptr;
We know that to access individual elements of an array we use the [] operator. For example, to access the first element of the array arr we would do arr[0]; to access the next element, arr[1], and so forth.

Like any other integer, we can use the & operator to get the address of an element in the array. For example, to get the address of the first element in the array, we could do &arr[0] and to get the address of the last element in the array we could do &arr[3]. So let's say that we want ptr to point to the first element of the array:


ptr = &arr[0];
Easy enough. Now with that done, let's say we want ptr to point to the second element of the array. We could do this one of two ways. We could do it just as we did above, as in:

ptr = &arr[1];
or, we could use our knowledge of pointer arithmetic to increase the value of ptr by 1, as in:

ptr += 1;
Just like every other time we've seen a pointer to an integer, we can then dereference the pointer to get at the integer's memory. So in this case, we could do *ptr to access arr[1].

So, if pointer points to the beginning of the array, as it does after executing the instruction ptr = &arr[0], then we now have two ways to access each element of the array. The first way is the one you already know, accessing the element in an array at position n , by writing arr[n]. The second method takes advantage of pointer arithmetic. We use pointer arithmetic to move us to the nth place in the array, and then dereference it to get the integer at that index. This means that arr[n] and *(ptr + n) are synonymous.

We can take this one step further. As mentioned earlier, arrays are basically pointers. In fact, the variable arr is itself a pointer (a constant one, meaning we can't change the address it points to, but nonetheless it points to something). As arr is itself a pointer, we can do pointer arithmetic on it like any other pointer, so we could access the nth element of arr using *(arr + n). This is exactly the same as doing arr[n], and the process of adding the value n to the pointer arr and then dereferencing it is most likely what is taking place behind the scenes in the computer when you use arrays.

Similarly, we can use the [] operator on a pointer. If ptr = arr, then it is perfectly valid syntax to do ptr[0], ptr[1], etc.

Follow Us