Last
updated: Tuesday 15th March 2005, 5:31 PT by AHD
Cast
your mind back to our first introduction to variables. You already know that a variable has a
name and a data type. Variables
are stored in memory, and the size of memory used to store a variable depends
on the type of the data to be stored.
Each byte of memory has an address which the compiler uses to locate a
variable and its contents.
A
"pointer" is a special kind of variable. A pointer is a variable that contains the address of another
variable. Because a pointer
contains the address of a variable it is said to "point to" that
variable.
This
document introduces the important topic of pointers in C and C++. You will learn how to declare and
initialize a pointer, and how to use pointers that point to simple
variables. If you continue your
studies of the C or C++ language by taking an advanced course, you will study
pointers in detail, use pointers with arrays and strings, pass pointers to functions,
use arrays of pointers, pointers to pointers, pointers to structures and
pointers to functions. In fact, an
advanced course will devoted some considerable time to the use of pointers
because the C/C++ language can only be used to its full potential by using
pointers.
All
serious C and C++ programs use pointers.
In fact, there are some operations which cannot be performed without
using a pointer. For instance,
pointers can access variables that would not normally be visible to a function
and pointers enable multiple values to be returned from functions.
The
following is a list of common uses of pointers:
·
returning more than one value from a function
·
manipulating strings
·
accessing variables not normally visible
·
array element manipulation
·
passing the address of one function to another function
·
dynamic memory allocation
This
section uses the program pointers01.cpp to demonstrate how to
declare and initialize a pointer variable, and how pointers are used with
simple variables (ones which store a single value).
//
Program: pointers01.CPP
//
Programmer: A.H.Dawson
// Date:
Tuesday 11th November 2003, 8:57 PT
//
Program to demonstrate the use of pointers
#include
<iostream.h>
#include
<conio.h>
#include
<stdio.h>
void main
(void)
{
char letter = 'A';
char *ptr;
ptr = &letter;
/* printf is a C function used to
print to the screen the data in the () */
/* I am using it in this program
instead of the C++ cout so that */
/* I can display the value of the
pointer - the address, as an integer */
printf( "letter = %c \n",
letter );
/* %c is the format code for
printing a character */
printf( "&letter = %u
\n", &letter );
/* %u is the format code */
printf( "ptr = %u \n ",
ptr );
/* for an unsigned integer
*/
getch();
}
The
output from pointers01.cpp is as follows:

Note: when you run the code you will
get a different value for the address (not 6618627) - but &letter and ptr will always have the same value.
The first statement in pointers01.cpp declares a variable named letter and initializes it with the value 'A'.
char
letter = 'A';
The second statement
declares a pointer variable:
char *ptr;
This declaration
indicates that ptr is the name a pointer
variable which will contain the address of an char variable.
When used in an expression, the pointer variable ptr represents an address.
The *
placed in front of the name ptr is the address operator
known as the indirection operator.
The indirection operator is placed in front of the name ptr to indicate that this variable is a
pointer variable. The
indirection operator is used in two ways in C/C++. In a declaration
such as the one shown above, it simply means "this variable is a
pointer". You will see its
second use later in this section.
The third statement of pointers01.cpp uses the other address operator
known as the address-of operator (&):
ptr =
&letter;
This statement results in
the address of the variable letter
being
assigned to the pointer variable ptr. The address of a variable is allocated
by the compiler. If you compile
and run pointers01.cpp yourself, the address
displayed will be different to the one shown in the output display above.
The following diagram
illustrates the concept of pointer variables.
The variable named letter is of type char, and hence uses one byte
of memory. Let's assume that the
address of this byte of memory is
8711. The variable letter contains the value 'A'.
letter
(address = 8711)
'A'
The
lines:
char *ptr;
ptr =
&letter;
would
then generate a pointer variable named ptr, and the address of the variable letter is stored in ptr:
ptr
8711
The
output statements of the program pointers01.cpp…
printf( "letter = %c \n ", letter );
printf( "&letter = %u \n ", &letter ); /* %u is the
format code */
printf( "ptr = %u \n ",
ptr );
/* for an unsigned
integer */
. . . print out the
contents of the variable letter ('A'), the address of the
variable letter (8711), and the
contents of the variable ptr (8711).
The second use of the
indirection operator is illustrated in the following program – pointers02.cpp. If the indirection operator is used in front of a
pointer variable in a statement which is not
a declaration, it refers to the value
contained at the address the pointer stores. Consider the following program:
/* Program:
pointers02.CPP */
/* Programmer:
A.H.Dawson */
/* Date Tuesday 11th
November 2003, 9:09 PT */
/* Program to
demonstrate the use of pointers */
/* Note: C++ is a
superset of C */
#include
<iostream.h>
#include
<conio.h>
#include
<stdio.h>
void main (void)
{
char letter = 'A';
char *ptr;
ptr = &letter;
printf( "letter = %c \n",
letter );
printf( "&letter = %u \n", &letter ); /*
%u is the format code */
printf( "ptr = %u \n", ptr );
/* for an unsigned integer */
printf( "*ptr = %u \n", *ptr ); /* value
as an unsigned integer */
printf( "*ptr = %c \n", *ptr ); /* value
as a char */
getch();
}
The
output from this code is as follows:

The last two lines of
program pointers02.cpp result in the value stored at the address contained by
the pointer variable ptr being displayed on the screen. Note that a character is stored as the
integer ASCII code, and can be displayed as an integer or as a character. The ASCII code for the character ‘A’ is
65.
Like any other variable,
a pointer variable must be declared before it is used. The value of a pointer variable (the
address it contains) may also change during the course of the program run. A pointer variable can have any legal
identifier name. The following
line shows the pointer declaration of program pointers02.cpp:
char *ptr;
It
looks just like any other variable declaration with a variable name and a
type. The declaration states that
the program has a pointer variable named ptr that can point to a data
object of type char.
Pointers don't have a type in the same sense that a simple variable has a
type. The type stated in a pointer
declaration refers to the type that the pointer points to, but the pointer
variable always contains an
address. Hence, the bytes storage
space required for a pointer is always the same for any particular computer
system, usually the same storage space as an integer (two or four bytes
depending on the implementation).
Just like any other variable, a pointer variable is stored at an address
allocated by the compiler. This
means that a pointer variable can point to another pointer variable which in
turn can point to another, and so on.
To
declare pointers to different types of variables, again the procedure is
similar to simple variable declarations.
The following statements are examples of pointer declarations to type int and float variables:
int
*i_ptr, *i_ptr_2;
float
*f_ptr;
Note
that if you declare more than one pointer on the same line, they both must be
preceded by the indirection operator.
In most cases you would declare a
pointer to a particular type, such as char. However, you can also declare a pointer to type void, which allows it to
point to any type of object.
After
declaring a pointer variable, storage space is reserved for it and this storage
space will contain random meaningless data until you initialize the
pointer. You initialize a pointer
variable with a statement such as:
ptr =
&value;
The
statement above assigns the address of value to ptr.
ptr then stores the address where value is stored.
The
third line of code in the following extract from the program pointers02.cpp shows the pointer variable ptr being initialized with the address of the char variable letter.
char letter =
'A';
char *ptr;
ptr = &letter;
printf( " letter = %c \n ", letter );
printf( " &letter = %u \n ", &letter ); /* %u is the
format code */
printf( " ptr = %u \n ", ptr ); /* for an unsigned integer */
The
last two printf statements result in the
address of the variable letter printed out to the screen.
The
line . . .
printf( " &letter = %u \n ", &letter ); /*
%u is the format code */
prints:
&letter = 8737
(Note: the actual number will be
different on different machines)
using
the address-of operator to obtain the address of letter directly, and the line
. . .
printf( "
ptr = %u \n ", ptr
); /* for
an unsigned integer */
prints:
ptr = 8737
using
the contents of the pointer variable
ptr.
The
relationship of the variable letter to the initialized variable ptr is shown in the following illustration:
![]()
![]()
8737 'A'
ptr letter
The value in the variable ptr is the start address of
the variable letter. The arrow linking the two
variables is a convention often used in text books on the C/C++ programming
language to illustrate this connection between a pointer variable and the
variable it points to.
You should take care not
to use uninitialized pointers.
Since a pointer which has not been initialized may contain any address -
including an operating system address, any reference to an uninitialized
pointer may change the contents of operating system memory, and cause the
system to malfunction.
Unpredictable consequences, such as for example an unexpected reboot of
the computer, may result.
Program pointers02.cpp shows that the pointer variable ptr is assigned an address constant (the address of letter obtained with the
address-of operator):
char *ptr;
ptr = &letter;
A pointer variable may
also be assigned the value of another pointer variable, as shown in the
following example lines of code:
char *ptr, *ptr2, *ptr3;
ptr = &letter;
ptr2 = ptr;
ptr3 = ptr2;
Once
we have a pointer that points to a variable, we have two ways to access the
data in that variable. The usual
way is the direct way, by using the variable's name as shown below:
int number = 10;
printf( "number = %d \n" , number
);
If we extend the code to
include a pointer to int,
and assign to the pointer the address of the variable number, then we can access the data in number by using the pointer. This sort of access is known as indirect access, and uses the indirection operator:
int
*ptr;
int number = 10;
ptr = &number;
printf( "number = %d \n" , number
);
printf( "number = %d \n", *ptr);
Both of the printf statements will access the same variable (number), the first by direct access and the second by indirect
access.
In
the same way that you can change the contents of a variable by using its name
as in:
number =
10;
you
could equally well use a pointer to the variable instead:
*ptr = 10;
The
following page shows a program which illustrates this point.
Before
you run the following program, study the code and try to predict the output.
/* Program:
pointers03.cpp */
/* Programmer:
A.H.Dawson */
/* Date: Tuesday 11th
November 2003, 9:19 PT */
/* Program to
demonstrate the use of pointers */
#include
<iostream.h>
#include
<conio.h>
#include
<stdio.h>
void main (void)
{
int number1 = 50;
int number2 = 100;
int *ptr1, *ptr2 ;
ptr1 = &number1;
ptr2 = &number2;
printf( "number1 = %d
\n", number1 );
printf( "number2 = %d
\n", number2 );
printf( "*ptr1 = %d \n",
*ptr1);
printf( "*ptr2 = %d \n",
*ptr2);
ptr2 = ptr1;
printf( "*ptr1 = %d \n",
*ptr1);
printf( "*ptr2 = %d \n",
*ptr2);
*ptr2 = 75;
printf( "*ptr1 = %d \n",
*ptr1);
printf( "*ptr2 = %d \n",
*ptr2);
getch();
}

A
pointer is an address, an address is an integer, but a pointer is not an
integer in the true sense of the word integer. You cannot do regular arithmetic on a pointer as if it was a
true integer. So what is pointer
arithmetic? To illustrate pointer
arithmetic, let’s revisit arrays…
Imagine
the elements of an empty array as a line of empty boxes standing side by
side. Each box can hold one byte
of data, and each box has an address, which is a number giving the location of
the box in memory.
4052 4053 4054 4055 4056
The
above bytes of memory might be reserved for example . . .
after
a declaration such as . . .
char my_array[5];
Consider
this program:
/*
Program: pointers04.cpp
Programmer: A.H.Dawson
Date: Tuesday 11th November 2003,
9:23 PT
Program to demonstrate the use of
pointers
*/
#include
<iostream.h>
#include
<conio.h>
#include
<stdio.h>
void main (void)
{
char my_array[5];
int i;
my_array[0] = 'A';
my_array[1] = 'B';
my_array[2] = 'C';
my_array[3] = 'D';
my_array[4] = 'E';
for ( i = 0; i < 5 ; i = i + 1 )
{
printf( "
my_array[%d] = %c ", i,
my_array[i] );
printf( "\t
&my_array[%d] = %u \n",
i, &my_array[i] );
/* %u is printf format
code for unsigned integer */
} /* %t is printf
format code for tab */
getch();
}
This
program will set up an array using 1 byte of memory for each element. The first element of the array is
assigned a value equal to the character 'A', the second element is assigned the character 'B' and so
on.
This
is the output on running the code:

Notice
the addresses go up in one byte chunks. The address in memory at which the
first element of an array starts is automatically set by the computer. Subsequent elements will have an
address relative to the start address.
For elements with a storage size of one byte this would be the start
address + 1, start address + 2, and so on. If the start address of the array named my_array was 8710, the addresses of the elements would be as shown in the
following diagram.
8710 8711 8712 8713 8714
![]()
![]()
![]()
![]()
A B C D E
If
the elements were 2 bytes in size (the size for storage of integers on some
machines), then the addresses of the elements would be in steps of two: 4052,
4054 etc. The computer
automatically handles the allocation of memory addresses for arrays, so you
don't need to worry about that.
Consider
this program:
// Program: pointers05.cpp
// Programmer: Anne Dawson
// Date: Tuesday 11th November 2003, 9:29 PT
// Program to demonstrate the use of pointers
#include
<iostream.h>
#include
<conio.h>
#include
<stdio.h>
void
main (void)
{
int my_array[5];
int i;
my_array[0] = 1;
my_array[1] = 2;
my_array[2] = 3;
my_array[3] = 4;
my_array[4] = 5;
for ( i = 0; i < 5 ;
i = i + 1 )
{
printf(
" my_array[%d] = %u ",
i, my_array[i] );
printf(
"\t &my_array[%d] = %u
\n", i, &my_array[i] );
/*
%u is printf format code for unsigned integer */
} /* %t is printf format code for tab */
getch();
}
This
is the output on running the code:

Notice
the addresses go up in four byte chunks, (the storage requirements may be
different on different machines, e.g. two bytes) because we now have an array
of integers, and each integer occupies 4 bytes on my machine. If the address of
the first element was 8706, the memory would look like this:
8706 8710 8714 8718 8722
![]()
![]()
![]()
![]()
1 2 3 4 5
So
getting back to pointer arithmetic…
If
I declare a pointer to type int,
then assign to it the address of the first element of an array, I can now refer
to the elements of the array by using the pointer. For example, consider the following code and its output:
/*
Program: pointers06.cpp
Programmer: Anne Dawson
Date: Tuesday 11th November 2003,
9:38 PT
Program to demonstrate the use of
pointers
*/
#include
<iostream.h>
#include
<conio.h>
#include
<stdio.h>
void main
(void)
{
int my_array[5];
int i;
int *ptr;
my_array[0] = 1;
my_array[1] = 2;
my_array[2] = 3;
my_array[3] = 4;
my_array[4] = 5;
for ( i = 0; i < 5 ; i = i + 1 )
{
printf(
"my_array[%d] = %u \n",
i, my_array[i] );
}
ptr = &my_array[0];
printf( "my_array[0] contains
%u \n",*ptr );
ptr++; /* THIS IS POINTER
ARITHMETIC */
/* the above statement increases
the value of ptr */
/* by a value equal to the size in
bytes of the data */
/* it points to. So for an integer
the address increases */
/* by 4 bytes, thus the pointer now
points to the next element */
/* in the array */
printf( "my_array[1] contains
%u \n",*ptr );
getch();
}
The
output:

Explanation:
8706 8710 8714 8718 8722
![]()
![]()
![]()
![]()
1 2 3 4 5
The
following line of the program puts the address of the first element (8706) into
the pointer ptr.
ptr = &my_array[0];
The
following line of the program prints out the contents of the address held by ptr (1).
printf( "my_array[0] contains %u
\n",*ptr );
The
followng line is an example of pointer arithmetic:
ptr++;
This
statement increases the value of ptr
by a value equal to the size in bytes of the data to. So, since the pointer
points to an integer the address the pointer contains increases by 2 bytes,
thus the pointer now points to the next element in the array (address
8710). The contents at this new
address are printed out by the following line of code:
printf( "my_array[1] contains
%u \n",*ptr );
Note:
you may also decrement a pointer using ptr--. It
works in exactly the same way.
This
document is complementary to the chapter in the textbook on "Pointers and
Dynamic Arrays" (chapter 12 or 11, depending on the edition). You should ensure that you read the
first two sections of this chapter as it contains additional material not
covered in this document. The
third section of the chapter ("Classes and Dynamic Arrays") is not
covered in this course.