The Basics

Pointers are one of the most important concepts to understand in the C programming language, because pointers are the basis for most of the more complex data structures that are commonly used in later levels.

Most people who have trouble programming in C do so because they don't understand what pointers are and how they work. The simplest way to think of pointers is to picture them as pointing to something else, which is exactly what they do.

When a program is run, all of it's variables are loaded into different memory locations. Each location has a base address, which is the place where the variable begins. The memory location could be a 4 byte integer, a 20 byte array or a 50 byte structure, but no matter what, there is one base address that the data is accessed from.

Figure 1 - Memory Allocation
Figure 1 - Memory Allocation
Each block equals one byte of memory.

No matter what datatype a pointer is pointing to, it always contains the same value - a memory address. Consider the following C statements:

int data = 2112;
int *dataPTR;
dataPTR = &data;
The first line of code declares a variable called 'data' that stores the integer value 2112.

The second line declares a pointer that will point to an integer value. The asterisk (*) character is used with variables to create pointers. By placing the * before the variable name, the variable has become a special variable that will point to a memory address.

The third line of code sets the value of the pointer equal to the address of the variable named 'data', it does not set dataPTR equal to the value of data. The ampersand (&) symbol is the address operator. When you use &data, it represents the physical memory location of the variable 'data', not the value of the variable. What this means is that if the program loads into memory and the variable 'data' is placed in memory location ff0a5b, then ff0a5b is the address of 'data.'

Figure 2 - Pointer Values
Figure 2 - Pointer Values

As you can see in the above figure, the value of 'data' is stored in memory. The value of 'dataPTR' is the same as the memory address 'data' is stored at.


Pointer Manipulation

By now, you are probably wondering why pointers are so important. The frustrating thing is, that in most C programming courses, it's hard to see the point of a lot of the more complex things because the example programs you are asked to write could be done a lot more easily without the fancy tricks. The thing to remember is that the examples are meant to teach how to use the code, not necessarily a brilliant use for it. While you might be able to write the program better using just the variable instead of pointers, you will be grateful when you get into abstract data structures.

So the question is, how do you use pointers? The key to using pointers is knowing and understanding the usage of the * (dereferencing) and & (address) operators.

The first thing you have to do is give the pointer something to point to. The simplest way to do this is to use the &, or address, operator. This operator will give the physical memory address of the variable instead of the value of the variable. So to make dataPTR point to data, you would use:

dataPTR = &data;

This statement is read "dataPTR is equal to the address of data." So now, dataPTR is pointing to the variable data by 'knowing' where it is located.

The reciprocal of the address operator is the dereferencing operator (*). Now that dataPTR 'knows' where data is located, you have to have some way of accessing data through the pointer. That's where the * operator comes in. What this operator does is gives the value of the variable that dataPTR is pointing to, instead of the memory address. Think of it this way:

dataPTR tells you the memory location of whatever it is pointing to.

*dataPTR looks in the memory address it is pointing to and returns that value, not it's own value.

So referring to Fig 2, you will see that dataPTR is pointing to memory location ff0a5b, and that the value stored at memory location ff0a5b is 2112. So the following code:

printf("dataPTR points to memory location %p", dataPTR);
printf("The value stored at memory location %p is %d.", dataPTR, *dataPTR);

Will result in:

dataPTR points to memory location ff0a5b
The value stored at memory location ff0a5b is 2112.

The actual value stored by a pointer is a memory address. Meaning that if you print out the value of dataPTR, it's going to give you a cryptic hexadecimal number that will most likely be different every time you run your program. By dereferencing the pointer, you can get some useful information out of it.



Here are a few simple coding examples that show how to use pointers.

dataPTR = &data;

This statement makes dataPTR point to data.

*dataPTR = 225;
data = 225;

Both of these statements have the same effect. While you are more familiar with the second method, the first is just as valid. It looks at dataPTR, and sees the memory address it is pointing to. Since dataPTR is dereferenced, it goes to that address, and changes that value to 225.

int secondPTR;
secondPTR = dataPTR;

This code will create a second pointer to the integer data type. The second line will make secondPTR point to the same place that dataPTR is pointing to.

Let's assume for a second that you have two variables, first and second, and two pointers, firstPTR and secondPTR.

*secondPTR = *firstPTR;
second = first;

Once again, these are equivalent statements, they both change the value of 'second' to equal that of 'first.'

*dataPTR = &data;

This is generally very bad. What this does is change the value that dataPTR is pointing to to the address of itself. This is one mistake that a lot of early C programmers may make. The thing you have to understand is that "dataPTR" will create, change, or use the address of the place dataPTR is pointing to. "*dataPTR" will create, change, or use the value of the place dataPTR is pointing to. So if you have your statement wrong, you may be unintentionally overwriting data that your program needs to run.




Copyright 1995-1997, Reality˛ Design