Lecture 14: Pointers |
A pointer is a special type of variable. In itself it contains no useful information. It is only an address to what (might) contain useful information. |
A pointer contains the address of a place in memory |
This is like keeping the address of an appartment
in my addressbook. It is only an address and nothing more.
type *name; |
int *p;
Now p is a pointer that points
to information of the type int.
float *f;
Now f is a pointer that points
to information of the type float. The value of f
itself is not of type float, because f
is a pointer and its value is an address. Only the contents of the
memory address that f is pointing
to contains information of type float.
&x returns address of variable x |
|
Let's declare a variable of type float x and a pointer to floats p:
float x; float *p; In
the figure on the left, x is a variable of type float that has
a value of 3.0. When we want the pointer p to point to this variable,
we can use
The value of p is now a memory address, namely the address
that contains the variable x. To show the contents of the memory
of what p points to, we can do this with
|
Picture the following situation. The figure below shows a part of the memory and its contents. A pointer p points to a place in this memory. If p is pointing to a byte (unsigned char) as shown in the top line, the contents of the address p are *p =129 (binary: 10000001), while with p pointing to the same place in memory, but pointing to an unsigned int*p = 25473 (binary: 0110001110000001), or p pointing to a long int (4 bytes, 32 bits) will give 743924609 (binary: 00101100010101110110001110000001). (Note that in Intel-processor-based computers numbers are stored with their lowest value bit [LSB=least significant bit] first).
Therefore, we have to specify the type the pointer is pointing at.
void main()
{
/* declare a word (unsigned
int) and a pointer to word: */
unsigned int *wordptr;
unsigned int w;
/* assign a value to the
word */
w = 25473;
/* let a 'pointer to word'
point to our word */
wordptr = &w;
/* show the contents of
the memory wordptr points to */
printf("%d", *wordptr);
}
output:
25473
Now let's see a more complicated example. We are going to create a pointer of type 'pointing to a byte (unsigned char)', and let it point to our unsigned int:
void main()
{
/* declare a word (unsigned
int) and a pointer to word: */
unsigned char *charptr;
unsigned int w;
/* assign a value to the
word */
w = 25473;
/* let a 'pointer to char'
point to our word */
charptr = &w;
/* show the contents of
the memory wordptr points to */
printf("%d", *charptr);
}
output:
129
(output for Borland C++ version 3.1 for MS-DOS.
On other computers or versions the output might be different)
This shows that we have to be careful what our
pointer points to. The value depends on the type!
Initialization of a variable is even more important
for pointers. Without initialization, a pointer points to a random part
of memory, where important programs might be running. These programs and
the computer can crash when we write in this place. The following program
might crash the computer. It defines a pointer and doesn't assign an address
to it. The value of the pointer (the address) is therefore unpredictable.
The program then writes a value in this random address.
void main() { int *p; *p = 0;
|
Why use pointers? There are several reasons
to use pointers instead of normal variables. The most important ones are
|
|
Speed: Imagine you want to
write a progam that moves a lot of information around. In the conventional
way, this would mean copying a lot of bytes from one part of the memory
to another part. Take for example the sorting of an array with name.
(a pointer is just 4 bytes in Intel computers).
Flexibility: If, at the beginning of the program we do not know yet how many variables we need we would have to reserve space for all possible eventualities. If we want to write a program that calculates the first N prime numbers, with N given by the user, we would have to declare an array of maximum size to be sure that we can fit the users request in it. With this we would completely occupy the memory of the computer. Nothing else can run anymore. Much nicer would be if we could declare the array (the variables) dynamically so that we only use memory if we really need it. With pointers this is easily possible.
The pointers and the idea of dynamic creation
of variables also lies at the basis of object-oriented programming, which
is the type of programming of every modern computer language. Object oriented
programming is outside the scope of this lecture, though.