Search Contact information
University of Cambridge Home Department of Engineering
University of Cambridge >  Engineering Department >  computing help
next up previous contents
Next: Strings Up: ANSI C for Programmers Previous: Functions   Contents

Pointers

Even if you don't use pointers yourself, the code you'll learn from will have them. Suppose i is an integer. To find the address of i the & operator is used (&i). Setting a pointer to this value lets you refer indirectly to the variable i. If you have the address of a pointer variable and want to find the variable's value, then the dereferencing operator * is used.
...
int i;
/* The next statement declares i_ptr to be a pointer at 
   an integer. The declaration says that if i_ptr is 
   dereferenced, one gets an int.
 */ 
int *i_ptr;
i_ptr = &i; /* initialise i_ptr to point to i */

/* The following 2 lines each set i to 5 */
i = 5;
*iptr = 5; /* i.e. set to 5 the int that iptr points to */
Pointers aren't just memory addresses; they have types. A pointer-to-an-int is int* and is of a different type to a pointer-to-a-char (which is char*). The difference matters especially when the pointer is being incremented; the value of the pointer is increased by the size of the object it points to. So if we added
     iptr=iptr+1;
in the above example, then iptr wouldn't be incremented by 1 (which would make it point somewhere in the middle of i) but by the length of an int, so that it would point to the memory location just beyond i. This is useful if i is part of an array. In the following fragment, the pointer steps through an array.
...
int numbers[10];
int *iptr;
int i;

numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;

iptr = &numbers[0]; /* Point iptr to the first element in numbers[] */

/* now increment iptr to point to successive elements */
for (i=0; i<3; i++){
   printf("*iptr is %d\n", *iptr);
   iptr= iptr+1;
}
...

Pointers are especially useful when functions operate on structures. Using a pointer avoids copies of potentially big structures being made.

typedef struct {
     int age;
     int height;
     char surname[20];
} person;

person fred, jane;

int sum_of_ages(person *person1, person *person2){
int sum;  /* a variable local to this function. */  

    /* Dereference the pointers, then use the `.' operator to get the 
       fields */  
    sum = (*person1).age + (*person2).age;
    return sum;
}
Operations like (*person1).age are so common that there's a special, more natural notation for it: person1->age.

To further illustrate the use of pointers let's suppose that in the first example on page [*] we wanted to pass to the function mean the variable where we wanted the answer stored. Since we no longer need mean to return a value, we can make it return void. Let's first try:-

#include <stdio.h>
#include <stdlib.h>

void mean(int a, int b, int return_val )
{
  return_val = (a + b)/2;
  printf("return_val in mean in %d\n",return_val);
}

main()
{
int i, j;
int answer;
   i = 7;
   j = 9;

   mean(i,j, answer);

   printf("The mean of %d and %d is %d\n", i, j, answer);
}

This won't work. Although return_val is set to the right value in mean, answer isn't. Remember, return_val and answer are separate variables. The value of answer is copied into return_val when mean is called. The mean function doesn't know where answer is stored, so it can't change it. A pointer to answer has to be given to mean().

#include <stdio.h>
#include <stdlib.h>
/* Note the form of the ptr_to_answer declaration below. It 
   says that if you dereference ptr_to_answer you get an
   int. i.e. ptr_to_answer is a pointer to an int.
 */  
void mean(int a,int b, int *ptr_to_answer)
{
  *ptr_to_answer = (a + b)/2;
}

main()
{
int i, j;
int answer;
   i = 7;
   j = 9;

   mean(i,j, &answer); /* Note that now we're passing a pointer
                        * to 'answer'
                        */

   printf("The mean of %d and %d is %d\n", i, j, answer);
}

There's a special value for null pointers (NULL) and a special type for generic pointers (void*). In K&R C , casting a pointer from one type to another didn't change its value. In ANSI C however, alignment is taken into account. If a long can only begin at an even memory location, then a pointer of type char* pointing to an odd location will have its value changed if cast into a long*.


next up previous contents
Next: Strings Up: ANSI C for Programmers Previous: Functions   Contents
Tim Love 2010-04-27