The Value of Pointers

Whenever you create a variable, you simply reserve space for it and label that space with the variable name. Creating a variable does not automatically give it an initial value; indeed, often the variable will have a garbage value. The situation is no different with pointers. Creating a pointer and using it without giving it a value is asking for trouble. Usually, dereferencing a pointer which has a garbage value will cause your program to stop running in unpleasant ways. Programming in a UNIX environment, you'll get used to getting "core dumps" when you have a pointer problem. These events inform you that you are trying to use pointers which have bad values.

To prevent the dreaded core dump (or at least some of them) we need to give our pointers useful values.

Taking the Address of an Object

The first way we can set the value of a pointer is to set it to point to an existing object. To do so, we need to be able to take the address of some variable or element in an array. That's what the ampersand (&) operator does. We've seen it in doing calls to scanf(), but we've never really studied it. An expression such as &x is evaluated to be the address of the variable x and the expression has type "pointer to foo" where x is of type foo.

Take for example the following code fragment:

int x, *x_ptr ;

x_ptr = &x ;
x = 5 ;
printf( "%d\n", *x_ptr ) ;

which prints out 5.

Copying Pointers

Another way to set the value of a pointer is to assign another pointer to it. For example, suppose that p points to some object and that q is a pointer of the same type as p. The statement:

q = p ;

will make both p and q point to the same thing. This is clear when we remember that the value of a pointer is the address of the thing to which it points. Assigning one variable to another copies the value of the variable on the right to the one on the left. After such an assignment, the pointer on the left now has the same value as the one on the right which means that it points to the same object.

Allocating New Objects to Point To

Sometimes we'd like to create data space while the program is running rather than just when the program is being compiled. In other words, we'd like to create variables that we haven't declared names for. By using pointers, the C standard library provides some functions for managing such data storage. The only one of these we'll be looking at here is malloc(). malloc() takes as an argument the number of bytes which we want to allocate and it returns a pointer to the new object. The usual way we use malloc() is:

p = (foo *)malloc( sizeof( foo )) ;

if p is a pointer to a foo. The (foo *) preceding the malloc() tells the compiler to convert the pointer malloc() returns to a pointer to a foo. malloc() has no way of knowing what type of object you want to point to, only how big it is. The sizeof( foo ) evaluates to the number of bytes in a foo. This is a portable way of determining the size of an object.

Which of these are valid assignment to pointers? Assume that p is a pointer to a character, c is a character, q is a pointer to an integer and x is an integer.

p = &c ;
p = q ;
q = x ;
q = (int *)malloc( 100 * sizeof( int )) ;
p = c ;