Tutorial six. About pointers

Pointers in C

Once you get the concept, pointers are easy to work with and let you create some powerful software in C. It’s probably fair to say that without pointers, you are limited in what you can write.  These are single page bite size tutorials which can usually be run on either codepad.org or ideone.com.

So what is a pointer? Answer it’s a variable that holds the address of another variable. That’s it!

Pointers also specify the type of variable pointed to. Here’s an int and a pointer to an int in the example below.

#include <stdio.h>

int a = 45;
int *b = &a;

int main(int argc, char* argv[])
{
  printf("a= %d\n\r",a);
  a++;
  printf("b= %d\n\r",b);
  printf("*b= %d\n\r",*b);
  return 0;
}


So a starts with the value 45. The second line needs some explaining.


int *b = &a;

This declares a pointer b to an int. The pointer is initialized with the address of a. The &a; means address of a and is the actual memory location in RAM where the variable a is stored.

Most of the time you never need to know what the actual address is, you just use it as a way of accessing the variable pointed to, i.e. a.

On my PC this outputs:

a= 45
b= 15888384
*b= 46

The second value will vary almost every time the program is run. Because b points to a, the value *b is always the same as the value a. Because of the a++, the output value of *b is 46. View it running on ideone.com.

Why are Pointers Important?

When used with a couple of functions for allocating and freeing dynamic memory, pointers let you allocate just the right amount of memory for the program’s needs.

Consider if you were writing a text editor. Without pointers you’d have to allocate enough room statically to hold most of text file. How much is enough? 100K, 5Mb or what? No one size suits every purpose. If you made it allocate 5MB every time it ran, it would be very inefficient.

Arrays and structs are fixed size, so the memory used for these is statically allocated and decided at compile time, not when you run it. Likewise for all scalar types (int, float etc) except pointers. All take up statically allocated memory and can never change it.

For allocating and freeing dynamic memory the functions are malloc() and free(). You request a block of ram with malloc() when you need it and get a pointer to that ram. When you’ve finished with it you then free() it.

Pointer Arithmetic

You may wonder why you would do arithmetic on pointer addresses. It’s used a lot with C strings. A string is defined as a char *, that is a pointer to a char. You could store a string in an array of char but the array would have a fixed size and you’d have to track the real length of the string.

Instead C manages it for you by inserting a zero value at the end of the string. In most cases you don’t have to worry about it but when allocating memory using malloc (which I’ll cover in the next tutorial) you always have to add 1 to the length requested.

This example below shows a string and one of the functions that C provides in a library called string.h. Libraries will be covered in a future tutorial as will printf format codes. I have used %d (for ints) and also %c for a single char and %s for a string.

#include <stdio.h>
#include <string.h>

char * name="David";

int main(int argc, char* argv[])
{
  int i;
  char * c;
  printf("Name = %s\n\r",name) ; 
  printf("Length of name is %d\n\r",strlen(name)) ;
  c= name;
  i=0;
  while (*c) {
    printf("Char %d is %c\n\r",i,*c) ;
   i++;
   c++;
  }
  return 0;
}

When run, this outputs:

Name = David
Length of name is 5
Char 0 is D
Char 1 is a
Char 2 is v
Char 3 is i
Char 4 is d

There’s a slight difference between the ideone code and the listing above. I added a \0 on the end of the string but it made no difference.

Pointer arithmetic uses the pointer type (i.e. of what is pointed to) to determine how far a pointer moves in memory when you increment it. In the example below, I’ve used an array of ints and an int * iptr to increment through the array.

 

#include <stdio.h>

int values[]={0,2345,-8907,15,999999};

int main(int argc, char* argv[])
{
  int i;
  int * iptr;
  printf("Sizeof values = %i\n\r",sizeof(values)) ;
  iptr=values;
  i=0;
  while (*iptr != 999999) {
    printf("Value %d is %d\n\r",i,*iptr) ;
    i++;
    iptr++;
  }
  return 0;
}

When run this outputs:


Sizeof values = 20
Value 0 is 0
Value 1 is 2345
Value 2 is -8907
Value 3 is 15

That correctly walks the array and each iptr++, adds four (the size of an int) to the actual pointer value. Arrays and pointers work very well together. An array occupies a statically allocated block of memory, so using pointers with them works well.

Note however the line iptr = values. With arrays the name of the array provides the address of the array as far as the compiler is concerned. No & is needed. If you wanted to point iptr to the address of values[0] (the first element), you do need to use & as with most other variables.


iptr=&values;[0];

Don’t forget that values is the same as &values;[0]!

In the next tutorial, I’ll continue with pointers.

Link to previous tutorial

Link to next Tutorial

(Visited 110 times, 1 visits today)