Pointers

Contents

Declaring a pointer

Pointers have a type just like everthing else. The type of the pointer is the the same as the type of the thing pointed to by the pointer. To declare a pointer to a integer, you have a declaration of:
    int *pointer_name;
  
The
*
is can be repeated to create a nested set of pointers, one
*
for each level of nesting. It is also used as the derefering operator, see below.

The & Operator

In C there are to operators that act on pointers
&
yields the address of the varible in acts on
eg:
&k
will yield the memory address of k.

The * Operator

The
*
operator will dereference ie get the value at the memory address stored in the value operated on, eg
*j
will get the value stored at the memory location stored in j.

Basic Usage

In C a pointer enables you to store the location of some other value in memory and write to the memory location directly. For example:
    int k = 5;
    int *j = &k;
  
will store the location of k in the varible j. Hence dereferinging
j
will yield the value of
k
, in this case 5. For clarity the same is shown below but in c(sort of)
    int k = 5;
    int *j = &k;

    *j == k == 5;
  

Pointers to Pointers

You can create a pointer to another pointer, indeed it would be possible to have many nested levels of pointers, eg a pointer to a pointer to a pointer(ie pointer-pointer-pointer). These are useful where you wish to allocate memory inside a function where the calling function mearly contains an uninitalized pointer to the memory that will be created by the new function, eg when reading files in.
Extending the above example
    int k = 5;
    int *j = &k;
    int **i = &j;
  
i
is a pointer that stores the address of j, which is itself a pointer to the memory storing the value of k.

If you wanted to get the value of
k
given the pointer
i
you would need to do
**i
this would give you the value of
k
. If you wanted to change where the pointer
j
points to, you would only need to dereference
i
once instead of twice.

The upshot of pointers to pointers

The use case for a pointet to a pointer is best seen in the example program below:
The code will not compile do not just copy it it is provided to illustrate the principles.
    void readfile(char **filestorage){
      //allocate a region of memory for the file to be stored in
      //note that we are only doing * once as we are changing the memory location held in the pointer called filestorage, since this function was given the memory location of a pointer which was declared in main
      //by deferencing once malloc will set the memory location stored in pointer called filestorage which is declared in main
      //in this case I have chosen to request 50 bytes of memory.
      *filestorage = malloc(50);

      //set file contents by double dereferencing the pointer to a pointer to write to the actual memory location holding the value, this memory location will be on the heap and was assigned by malloc above
      **filestorage = "hello";
    }

    int main(){
      //create a pointer called filestorage, since this is a pointer it can only hold a memory location and at the moment it does not point to a specific location in memory
      char *filestorage;

      //call the function making sure to pass the memory location of the pointer to it
      readfile(&filestorage);

      //since we have a plain pointer now we can simply dereference it to get the value stored at the underlying memory location.
      filecontents = *filestorage;
    }
  

Putting it all together

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

    int main(){
      int k = 5;
      int *j = &k;
      int **i = &j;

      printf("value stored at k=%d\n", k);
      printf("memory address of k=%p\n\n", &k);
      printf("memory address of j=%p\n", &j);
      printf("value stored in j=%p\n", j);
      printf("value of the int pointed to by j=%d\n\n", *j);

      printf("memory address of i=%p\n", &i);
      printf("value stored in i=%p\n", i);
      printf("value of the thing pointed to by i=%p\n", *i);
      printf("value of the int pointed to by the pointer pointed to by i=%d\n", **i);
    }
  


This produces when run (I have replaced the memory addresses):
    value stored at k=5
    memory address of k=0x15

    memory address of j=0x19
    value stored in j=0x15
    value of the int pointed to by j=5

    memory address of i=0x25
    value stored in i=0x19
    value of the thing pointed to by i=0x15
    value of the int pointed to by the pointer pointed to by i=5
  

Pointer arithmetic

You can perform some basic arithmetic on pointers, addition and subtraction, multiply and divide are not possible.

Pointer arithmetic is useful in some situations where the array operator does not do what you want, or you want to pass an array to a function but starting offset from the start of the array. The number you choose to operate on the address by is multipied by the size of the type of the pointer for example if the size of
int
on your machine was 4, then adding 1 to a pointer adds 4 to the underling memory address, as memory is counted in bytes.