Pointers

# Pointers.

Pointers are at the heart of C. When you crack this subject, you have got the worst of C behind you. Before you tackle pointers though, you should get a grip on arrays.

- First principles.
- Definition of a pointer.
- Pointers to strings.
- Pointers to arrays.
- Char arrays verses char pointers.
- Void pointers.
- Pointers to pointers.
- Pointers to functions.
- Linked lists.

## First Principles.

To understand pointers, it may be worth understanding how normal variables are stored. If you disagree, Click here to move on.

What does the following program realy mean?

            main()
    	{
      	    int Length;
    	}

In my mind, it means, reserve enough storage to hold an integer and assign the variable name 'Length' to it. The data held in this storage is undefined. Graphically it looks like:

          (Address) (Data)
               ---- ----
              | F1 |   <------- Length
              |----|----|
              | F2 |    |
              |----|----|
              | F3 |    |
              |----|----|
              | F4 |    |
               ---------

To put a known value into 'Length' we code,

    	main()
    	{
    	    int Length;
      	    Length = 20;
            }

the deciamal value 20 (Hex 14) is placed into the storage location.

          (Address) (Data)
    	   ---- ----
              | F1 | 00 <------- Length
              |----|----|
              | F2 | 00 |
              |----|----|
              | F3 | 00 |
              |----|----|
              | F4 | 14 |
               ---------

Finally, if the program is expanded to become

          main()
          {
              int Length;

              Length = 20;

              printf("Length is %d\n", Length);
              printf("Address of Length is %p\n", &Length);
          }

The output would look something like this .....

          Length is 20
          Address of Length is 0xF1

Please note the '&Length' on the second printf statement. The & means address of Length. If you are happy with this, you should push onto the pointers below.

## Pointer definition.

A pointer contains an address that points to data.

An example of code defining a pointer could be...

          main()
          {
              int *Width;
          }

A graphical representation could be...

          (Address) (Data)
               ---- ----
              | F1 |    <------- Width
              |----|----|
              | F2 |    |
              |----|----|
              | F3 |    |
              |----|----|
              | F4 |    |
               ---------

So far, this variable looks the same as above, the value stored at 'Width' is unknown. To place a value in 'Width' you could code.

          main()
          {
              int *Width;                                 /* 1 */

              Width = (int *)malloc(sizeof(int));         /* 2 */

              *Width = 34;                                /* 3 */
          }

          (Address) (Data)
               ---- ----
              | F1 | 00 <------- Width
    	  |----|----|               (Data) (Adress)
              | F2 | 00 |                 ---------
    	  |----|----|         -------> 00 | D1 |
    	  | F3 | 00 |        |       |----|----|
    	  |----|----|  *Width|       | 00 | D2 |
    	  | F4 | D1 | -------        |----|----|
    	   ---------                 | 00 | D3 |
    	                             |----|----|
    				     | 22 | D4 |
    				      ---------

Statements 2 and 3 are important here:

2) The malloc function reserves some storage and puts the address of the storage into Width.

3) *Width puts a value into the storage pointed to by Width.

Unlike the Length = 20 example above, the storage pointed to by 'Width' does NOT contain 34 (22 in Hex), it contains the address where the value 34 can be found. The final program is...

          main()
          {
              int *Width;

              Width  = (int *)malloc(sizeof(int));
    	  *Width = 34;

    	  printf("  Data stored at *Width is %d\n", *Width);
    	  printf("       Address of Width is %p\n", &Width);
    	  printf("Address stored at Width is %p\n",  Width);
          }

The program would O/P something like.

              Data stored at *Width is 34
    	       Address of Width is 0xF1
    	Address stored at Width is 0xD1

A pointer can point to any data type, ie int, float, char. When defining a pointer you place an * (asterisk) character between the data type and the variable name, here are a few examples.

    	main()
    	{
    	    int    count;		/* an integer variable              */
    	    int   *pcount;		/* a pointer to an integer variable */
    	    float  miles;		/* a floating point variable.	    */
    	    float *m;			/* a pointer			    */
    	    char   ans;			/* character variable		    */
    	    char  *charpointer;		/* pointer to a character variable  */
    	}

## Pointers to arrays

When looking at arrays we had a program that accessed data within a two dimensional character array. This is what the code looked like.

            main()
            {
              char colours[3][6]={"red","green","blue"};
            }

The code above has defined an array of 3 elements, each pointing to 6 character strings. You can also code it like this. Which is actually more descriptive because it indicates what is actually going on in storage.

            main()
            {
              char *colours[]={"red","green","blue"};
            }

Graphically it looks like this:

         colours  *colours *(colours+2) **colours
              |         |       |           |
              |         |       |           |
              V         V       V           |
             ---       -----------          |
            |   |---->|   |   |   |         |
             ---       -----------          |
                        |   |   |           V
                        |   |   |         -----------------------
                         --------------->| r | e | d |   |   |   |
                            |   |         -----------------------
                            |   |
                            |   |          -----------------------
                             ---|-------->| g | r | e | e | n |   |
                                |          -----------------------
                                |
                                |          -----------------------
                                 -------->| b | l | u | e |   |   |
                                           -----------------------
    		            	        A           A
                                            |           |
                                            |           |
                                    **(colours+2)   *(*(colours+2)+3)

    	printf("%s \n", colours[1]);
    	printf("%s \n", *(colours+1))

will both return green.

## Char Arrays verses Char pointers

What is the difference between these two lumps of code?

      main()
      {
          char colour[]="red";
          printf("%s \n",colour);
      }
      main()
      {
          char *colour="red";
          printf("%s \n",colour);
      }

The answer is, NOTHING! They both print the word red because in both cases 'printf' is being passed a pointer to a string.

An array of 4 bytes is reserved and the text 'red' placed into the storage array. The contents of the array can be chaged later BUT on the left, the size of the array is fixed.

Here is a picture of the example on the right. The 'r' of 'red' is stored at address 10, the 'e' is at address 11 etc.

At this point it maybe worth looking at the malloc function.

## Void Pointers

There are times when you write a function but do not know the datatype of the returned value. When this is the case, you can use a void pointer.

      	int func(void *Ptr);

      	main()
      	{
                char *Str = "abc";

                func(Str);
      	}

      	int func(void *Ptr)
      	{
      	    printf("%s\n", Ptr);
      	}

Please note, you cant do pointer arithmatic on void pointers.

## Pointers to pointers

So far we have looked at pointers to data, but there is no reason why we should not define a pointer to a pointer. The syntax looks like this.

    	main()
    	{
    	    char **DoublePtr;
    	}

A common use for these is when you want to return a pointer in a function parameter.

       	#include 		/* malloc */

    	void Func(char **DoublePtr);

    	main()
    	{
                char *Ptr;

    	    Func(&Ptr);
    	}

    	void Func(char **DoublePtr)
    	{
    	    *DoublePtr = malloc(50);
    	}

## Pointers to functions

Pointers to functions can be used to create 'callback' functions. An example of these pointers can be seen in the qsort function.

### Examples.

Simple example passing a function pointer.

Example passing 'int' variables.

Example passing 'char' and 'char *' variables.

## See Also:

VOID keyword.

function arguments.

linked lists.

Strings.

Arrays.

Top | Master Index | Keywords | Functions