A pointer is a variable that holds the address to a variable. The address of a
variable is where it is stored in the computer's memory. Pointers allow us
to create dynamic data structures, handle variable parameters passed to functions,
and they also give us an alternate way of working with arrays. A pointer can
point to any type of variable that is available and is used just like any other
type of variable. One thing many people are confused about when first learning
pointers is that the pointer variable only contains a memory address, it does not
contain the value of the variable that it is pointing to. Let's see some examples
to explain this concept more clearly
Pointers have many of the characteristics that a regular C variable has. This way we can declare and use them easily. To declare a pointer you must specify the data type that the pointer will point to and then the name of the pointer. Here is a quick example of a pointer to an integer.
Simple enough eh? Well one thing to keep in mind is that this pointer in not pointer to any data as of yet. Here is what we have done by declaring the pointer.int ip*;
C can get the memory address of a variable by referencing it. The amperstand is used as the referencing operator and it is placing in front of the varialbe that you wish to reference. In the above example we referenced the integer variableint i = 5; ip = &i;
i
and then assigned that memory address to the pointer ip.ip = &i;
This is because the C uses the asterik to dereference a variable, and to declare a pointer. Dereferencing gives us the contents of the memory address that is pointed to. So if we used*ip = &i;
*ip = &i
that would put the memory address of i
as the contents of
the pointer ip
. The first thing that is wrong with doing that is that the pointer is
still uninitialized. And the second thing wrong with the statement is that it would put the memory
address into ip
's contents, the pointer would still point to nothing. When you are
assigning a memory address to a pointer you will not want to put the dereferencing operator (*) in
front of the name of the pointer, this means that you are going to work with the actual value of the
pointer which should only be a memory address. When you need to change the contents of the variable
that a pointer points to you would use the *. Here is an example followed by an illustration.
int i = 5; int *ip; ip = &i; // Point ip to the memory address of variable i. *ip = 10; // Change the contents of the variable ip points to to 10.
Now that we have talked about basic pointers, let's move on to the next step. In the first section
we discussed pointers to single variables. What happens when we create a pointer that points to
an array? C has a very close link between pointers and arrays which may confuse the beginner, so
we will spend a little time discussing their similarities and differences.
As you may recall an array is a group of cells of a specified length that is created in the computer's
memory, we can access the different cells in the array by specifying the element number, or position,
in the array. Looking at how the memory of an array is setup will help us understand how all this
works. Let's say we wanted to create an array that holds five integers. First we would declare the
array...
Now let's look at an illustration to explain how this array looks in the computer's memory...int a[5];
a
we would have a pointer to the first element of
the array. If we increment the pointer it will point to the next element in the array, a[1].
Basically this assigns the memory address of a[0] the first element in arrayint a[10]; int *pa = &a[0];
a
to pointer
of type int
. Incrementing the pointer, pa++
, moves it to the next block
of memory which would be the second element of the array a
, &a[1]
. One
thing you need to know about arrays in C is that they will always decay, or turn, into a pointer, so
we could rewrite the assignment of the previous example as...
Since C will decay the arrayint a[10]; int *pa = a;
a
into &a[0] for us, this is completely legal to do. Say that
we wanted to declare a pointer to the fifth element in the array, we would do so like this...
or...int a[10]; int *pa = &a[4];
With all of this in mind you can do as I previously said about incrementing and decrementing pointers. This is called pointer arithmetic and it allows us to a pointer to reference any point in an array just by assigning the pointer a memory address inside of the array and then moving around by incrementing and decrementing the pointer. Here is an example with an illustration...int a[10]; int *pa = a+4; // Converts to &a[0] + 4 or &a[4]
int a[5] = {1,2,3,4,5}; int *pa = a; int i, total = 0; for(i = 0; i < 5; i++) { total = total + *pa; pa++; } printf("The total is %i", total);
In the first statement the pointerint a[5] = {1,2,3,4,5}; int *pa = a; pa = pa+3; // Increments the pointer by 3 *pa = *pa+3 // WRONG: Increments the contents of the variable // pointed to by pa by 3
pa
has moved 3 places in the array, now referring to
a[3]. In the second statement, the contents of *pa
, a[0]
, have 3 added to
them and then are assigned to *pa
, the value of a[0]. So now the values of the array
look like this {4,2,3,4,5}. As you can see, these are two very different things... make sure you
are really doing what you want by using the correct syntax!!
In the previous section we discussed how an array is decayed into a pointer by the compiler. So this means that when we pass an array to a function we are really passing a pointer to the first element of the array. Example:
Both of these functions can be used interchangably because they are both just memory addresses, or pointers. When you seechar function(char a[]); char function(char *a);
char a[]
you may think that you will be passing the function
an array, but as we discovered in the previous section all arrays decay into pointers. So when
you make the function call function(a)
, C will decay the array a
into
a pointer to the first element of the array, &a[0]
. This is how we can declare the
function with the argument as a pointer instead of an array. Note that you can use either array
indexing or pointer arithmetic inside of the function not matter how the array is passed.
All these functions will do the same thing except the do it using several different methods, keep in mind that sticking to pointers and pointer arithmetic generally results in faster executing code.void function (char a[], int len) { int k; for(k = 0; k < len; k++) { printf("%c", *a); a++; } } void function (char a[], int len) { int k; for(k = 0; k < len; k++) { printf("%c", a[k]); } } void function (char a*, int len) { int k; for(k = 0; k < len; k++) { printf("%c", a[k]); } } void function (char *a, int len) { int k; for(k = 0; k < len; k++) { printf("%c", *a); a++; } }