Lecture 14: Pointers


Pointer

A pointer is a special type of variable. In itself it contains no useful information. It is only an address to what (might) contain useful information.
 A pointer contains the address of a place in memory 

This is like keeping the address of an appartment in my addressbook. It is only an address and nothing more.


Declaration

To declare a pointer we can use the following syntax:
 
 type *name;
With name the name of the pointer variable and type the type of information the pointer name points to. This can be any type we have learned, from simple floats or ints to more complicated types we will learn later.
Examples:

  int *p;
Now p is a pointer that points to information of the type int.

  float *f;
Now f is a pointer that points to information of the type float. The value of f itself is not of type float, because f is a pointer and its value is an address. Only the contents of the memory address that f is pointing to contains information of type float.


Pointer operations

There are two pointer operations in C.
 
 
 &x returns address of variable
 *p is what pointer p points to (contents of address p) 

 
Let's declare a variable of type float x and a pointer to floats p:
  float x;
  float *p;

In the figure on the left, x is a variable of type float that has a value of 3.0. When we want the pointer p to point to this variable, we can use
  p = &x;

The value of p is now a memory address, namely the address that contains the variable x. To show the contents of the memory of what p points to, we can do this with
  printf("%f", x);
or via the pointer
  printf("%f", *p);


Type specification

Why is it important that we specify the type the pointer points to? This is best shown in an example

Picture the following situation. The figure below shows a part of the memory and its contents. A pointer p points to a place in this memory. If p is pointing to a byte (unsigned char) as shown in the top line, the contents of the address p are *p =129 (binary: 10000001), while with p pointing to the same place in memory, but pointing to an unsigned int*p = 25473 (binary: 0110001110000001), or p pointing to a long int (4 bytes, 32 bits) will give 743924609 (binary: 00101100010101110110001110000001). (Note that in Intel-processor-based computers numbers are stored with their lowest value bit [LSB=least significant bit] first).

Therefore, we have to specify the type the pointer is pointing at.


Example

Now let's see an example to show check if we have everything under control. We are going to create a pointer of type 'pointing to a word', and let it point to a word:
 

void main()
{
    /* declare a word (unsigned int) and  a pointer to word: */
  unsigned int *wordptr;
  unsigned int w;

    /* assign a value to the word */
  w = 25473;

    /* let a 'pointer to word' point to our word */
  wordptr = &w;
    /* show the contents of the memory wordptr points to */
  printf("%d", *wordptr);
}

output:
  25473

Now let's see a more complicated example. We are going to create a pointer of type 'pointing to a byte (unsigned char)', and let it point to our unsigned int:

void main()
{
    /* declare a word (unsigned int) and  a pointer to word: */
  unsigned char *charptr;
  unsigned int w;

    /* assign a value to the word */
  w = 25473;

    /* let a 'pointer to char' point to our word */
  charptr = &w;
    /* show the contents of the memory wordptr points to */
  printf("%d", *charptr);
}

output:
 129

(output for Borland C++ version 3.1 for MS-DOS. On other computers or versions the output might be different)
This shows that we have to be careful what our pointer points to. The value depends on the type!


Pointers and arrays in C

In C, all arrays are pointers. What this means is that when we declare an array
  int a[10];
this will
  - reserve 10x2 bytes in memory
  - assign the address of this memory to a
Therefore,
  a is of type 'pointer to int' and the value of a is an address.
 *a is the contents of address a. In this address resides the first element of a, namely a[0].
Therefore, the two forms, *a and a[0] are completely interchangeable and any of the two can be used at any time. We will see this later, when we discuss strings (arrays of char).
We have to remember this when we pass information to a function; when we pass an array, we pass the address of the array, rather than all the elements of the array. With arrays in C we always use the technique of passing by reference (see lecture 15).

Initialization

Initialization of a variable is even more important for pointers. Without initialization, a pointer points to a random part of memory, where important programs might be running. These programs and the computer can crash when we write in this place. The following program might crash the computer. It defines a pointer and doesn't assign an address to it. The value of the pointer (the address) is therefore unpredictable. The program then writes a value in this random address.
void main()
{
  int *p;

  *p = 0;
}


Why?


Why use pointers? There are several reasons to use pointers instead of normal variables. The most important ones are
 

  • Speed
  • Flexibility

Speed: Imagine you want to write a progam that moves a lot of information around. In the conventional way, this would mean copying a lot of bytes from one part of the memory to another part. Take for example the sorting of an array with name.
(a pointer is just 4 bytes in Intel computers).

Flexibility: If, at the beginning of the program we do not know yet how many variables we need we would have to reserve space for all possible eventualities. If we want to write a program that calculates the first N prime numbers, with N given by the user, we would have to declare an array of maximum size to be sure that we can fit the users request in it. With this we would completely occupy the memory of the computer. Nothing else can run anymore. Much nicer would be if we could declare the array (the variables) dynamically so that we only use memory if we really need it. With pointers this is easily possible.

The pointers and the idea of dynamic creation of variables also lies at the basis of object-oriented programming, which is the type of programming of every modern computer language. Object oriented programming is outside the scope of this lecture, though.


Quick Test

To test your knowledge of what you have learned in this lesson, click here for an on-line test.

Peter Stallinga. Universidade do Algarve, 13 November 2002