Programming in C: Pointers

When programming in C, a pointer is a very powerful programming tool. They can make doing certain tasks much easier, help improve efficiency in your program, and help you handle large amounts of data.

pointer is exactly what it sounds like it is, they "point" to locations in memory. The "number" stored within the pointer is the memory address of that variable. Once you have the address of a variable you can, in turn, retrieve the data at that memory address.

If you have a huge amount of data that you want to pass to a function, it would be a lot easier to pass the location to the function as opposed to copying every element you need. Another advantage of pointers are you can request memory for your program to use.

When a variable stores the address of another variable, we say that it is "pointing to" that variable.

A pointer requires a bit of new syntax because you need the ability of requesting the memory location you will be storing a value into and you need to be able to tell it what the value being stored at that location is. Since pointers are special in C, you need a special syntax to tell the compiler what type of memory its has to point to.

General Syntax

Here is the general syntax of a pointer declaration:

variable_type *variable_name; 

The use of the * denotes that you are declaring a pointer. Here is an example of declaring a pointer to an integer:

int *points_to_integer;

You can also declare a pointer and non-pointer in the same line:

/* Here is one pointer, one regular integer */
int *pointer, non_pointer;

In order for a pointer to point to another variable it has to have its memory location. To obtain the memory address of a variable, put an & in front of its name. This is called the address-of-operator since it returns the memory address.

Here is an example program which demonstrates how to use pointers:

#include <stdio.h>
int main()
{ 
int x; // A normal integer.
int *p; // A pointer to an integer ("*p" is an integer, so p must be a pointer to an integer).

p = &x; // Assign the address of x to p.
scanf("%d", &x); // Put a value in x (using p would have worked as well)
printf("%d\n", *p); // Note the use of the * to get the value.
return 0;
}

The above program will output the value stored in x. The integer is called x and a pointer to an integer is then defined as p. Then the program stores the memory location of the x (using the &) into the pointer called p. A user then enters a number to be stored in variable x, which is the same location that is pointed to by p. In fact, since we use an ampersand to pass the value to scanf, it is clear that scanf is putting the value in the address pointed to by p (NOTE: scanf works because of pointers).

The next line passes *p into printf. When you use an * before the name of a pointer, you are performing a "dereferencing" operation. Dereferencing looks at the address stored in the pointer, follows that address, and returns the value at that location in memory.

NOTE: The pointer is initialized to a specific memory address before it is used, if we did not do this it could be pointing to anything. If your pointer ends up pointing to something you do not want to your operating system will actually prevent you from accessing the data, intern causing your program to crash (in most cases). You should always initialize pointers before you use them!

Memory Allocation

Dynamic allocation of memory allows you to initialize pointers using the free memory in your system. Doing this is useful for setting up structures like linked lists and tree (which we will get to in a future tutorial), or anything that requires a non-fixed amount of memory.

This allows the program to run without knowing how much memory it will need at compile time, instead the program will get memory during the program's execution. 

The malloc function, as seen below, resides in stdlib.h header file, is used to initialize pointers with free memory. Malloc works like another function call taking the amount of memory requested in bytes as its argument. The function gets an amount of memory specified by the size you included in the argument, and then returns a pointer to that block of allocated memory.

Getting the appropriate size will depend on your variable type. To do this we use the sizeof function which takes an expression and returns its size. For example, sizeof(int) will return the number of bytes it takes to store an integer in memory.

#include <stdlib.h>

int *pointer = malloc(sizeof(int));

The above code sets pointer to a memory address that is the size of an integer. The memory pointed to by pointer then becomes unavailable to other programs. Note a slightly cleaner way of writing the above expression (as a programmer you are then protected against any future changes in variable types):

#include <stdlib.h>

int *pointer = malloc(sizeof(*pointer));

The careful coder should free this memory at the end of its usage, or else the memory could be lost to the operating system. This is often called a memory leak. After you are finished using a pointer, you should always free it. The free function returns the unused memory back to the operating system.

free(pointer);

After freeing a pointer, it is a good idea to reset it to point to 0, which makes the the pointer becomes a null pointer, in other words, it no longer points to anything. By doing this you can protect yourself from little errors that could cost you big (these are errors even experienced programmer will face).

The concept of pointers in C are a very powerful tool and it is important for programmers to fully understand how they work. If you have any questions about pointers please leave them in the comments below, and I will do my best to answer every single one.

If you have any suggestions of tutorials or any specific topics you want to see covered, please leave a comment below and I will take your suggestions into consideration. Follow me on Twitter to keep up-to-date on all the latest news and tutorials.

Programming in C: Structures

Programming Tutorials: Reader Suggestions