Professional Documents
Culture Documents
Introduction to Pointers
Pointers are one of the most powerful and confusing aspects of the C or C++ language. A pointer is a variable that
holds the address of another variable. To declare a pointer, we use an asterisk (* in-direction operator) between
the data type and the variable name:
int *pnPtr; // a pointer to an integer value
double *pdPtr; // a pointer to a double value
Note that an * (in-direction operator) placed between the data type and the variable name means the variable is
being declared as a pointer. In this context, the asterisk is not a multiplication. It does not matter if the asterisk is
placed next to the data type, the variable name, or in the middle — different programmers prefer different styles,
and one is not inherently better than the other.
Since pointers only hold addresses, when we assign a value to a pointer, the value has to be an address. To get the
address of a variable, we can use the address-of operator (&):
The type of the pointer has to match the type of the variable being pointed to:
int nValue = 5;
double dValue = 7.0;
Dereferencing pointers
The other operator that is commonly used with pointers is the dereference operator (*). A dereferenced pointer
evaluates to the contents of the address it is pointing to.
int nValue = 5;
cout << &nValue; // prints address of nValue
cout << nValue; // prints contents of nValue
int nValue1 = 5;
int nValue2 = 7;
int *pnPtr;
pnPtr = &nValue1; // pnPtr points to nValue1
cout << *pnPtr; // prints 5
pnPtr = &nValue2; // pnPtr now points to nValue2
cout << *pnPtr; // prints 7
Void pointers
The void pointer, also known as the generic pointer, is a special type of pointer that can be pointed at objects of
any data type! A void pointer is declared like a normal pointer, using the void keyword as the pointer’s type:
void *pVoid; // pVoid is a void pointer
void *pVoid;
pVoid = &nValue; // valid
pVoid = &fValue; // valid
However, because the void pointer does not know what type of object it is pointing to, it can not be dereferenced!
Rather, the void pointer must first be explicitly cast to another pointer type before it is dereferenced.
Null pointers
Sometimes it is useful to make our pointers point to nothing. This is called a null pointer. We assign a pointer a
null value by setting it to address 0:
C (but not C++) also defines a special preprocessor define called NULL that evaluates to 0. Even though this is not
technically part of C++, it’s usage is common enough that it will work in every C++ compiler:
int *pnPtr = NULL; // assign address 0 to pnPtr
As you can see, the size of the pointer is always the same. This is because a pointer is just a memory address, and
the number of bits needed to access a memory address on a given machine is always constant.
*pnPtr = 9;
pnPtr = &nOtherValue;
A short explanation about the 4 and the 2. A 32-bit machine means that pointers will be 32 bits in length, but
sizeof() always prints the size in bytes. 32 bits is 4 bytes. Thus the sizeof(pnPtr) is 4. Because pnPtr is a pointer to a
short, *pnPtr is a short. The size of a short in this example is 2 bytes. Thus the sizeof(*pnPtr) is 2.
anArray is actually a pointer that points to the first element of the array! Because the array variable is a pointer, you
can dereference it, which returns array element 0:
int anArray[5] = { 9, 7, 5, 3, 1 };
Pointer arithmetic
Both C and C++ languages allow you to perform integer addition or subtraction operations on pointers. If pnPtr
points to an integer, pnPtr + 1 is the address of the next integer in memory after pnPtr. pnPtr - 1 is the address of the
previous integer before pnPtr.
Note that pnPtr+1 does not return the address after pnPtr, but the next object of the type that pnPtr points to. If
pnPtr points to an integer (assuming 2 bytes), pnPtr+3 means 3 integers after pnPtr, which is 6 addresses after
pnPtr. If pnPtr points to a char, which is always 1 byte, pnPtr+3 means 3 chars after pnPtr, which is 3 addresses
after pnPtr.
When calculating the result of a pointer arithmetic expression, the compiler always multiplies the integer
operand by the size of the object being pointed to. This is called scaling.
short nValue = 7;
short *pnPtr = &nValue;
cout << pnPtr << endl; Because a short is 2 bytes, each address differs by 2.
cout << pnPtr+1 << endl;
cout << pnPtr+2 << endl;
cout << pnPtr+3 << endl;
It is rare to see the + and – operator used in such a manner with pointers. However, it is more common to see the ++
or — operator being used to increment or decrement a pointer to point to the next or previous element in an array.
The parentheses are necessary to ensure the operator precedence is correct — operator * has higher precedence than
operator +.
Note that *(anArray+1) has the same effect as anArray[1]. It turns out that the array indexing operator
([]) actually does an implicit pointer addition and dereference! It just looks prettier.
Arrays of Pointers
We can declare an array of pointers very easily. It is done like this:
int* hello[10];
This declares an array of 10 pointers, each of which points to an integer. The first pointer is called hello[0], the
second is hello[1], and so on up to hello[9]. These start of un-initialized - they point to some unknown point in
memory. We could make them point to integer variables in memory like this:
{
int* hello[10];
int a = 51, b = 46,……… c = 109;
hello[0] = &b;
hello[1] = &c;
hello[2] = &a; // etc.
}
#include <iostream.h>
int* hello[10];
void main ()
{ int a = 46, b = 109, c = 51, d = 66, e = 82, f = 47,
g = 40, h = 36, k = 70, l = 79;
hello[0] = &a;
hello[1] = &b;
hello[2] = &c;
hello[3] = &d;
hello[4] = &e;
hello[5] = &f;
hello[6] = &g;
hello[7] = &h;
hello[8] = &k;
hello[9] = &l;
int* temp;
int i,j;
Pointers to Arrays
Suppose you have an array of integer values called v. You can declare a pointer to a integer value and make it point
to the array as per normal:
This piece of code displays the number which the
int v[5] = {1004, 2201, 3000, 432, 500}; pointer p points to, which is the first number in
int * p = v; the array, namely 1004. Note we deliberately
didn't use the & sign when we set up the pointer.
cout << *p << endl; As we said earlier it is not needed as array
variable is a pointer itself to the first element of
the array.
The most important thing you have to remember is that, C++ tends to treat arrays almost as though they were
pointers, which is why you can set a pointer to an array straight rather than using the "address of" operator. The
instruction p = v makes the pointer point to the address of the array. The number at this address is the first element
of the array, so that is the value produced when you access *p:
C++ gives some extra arithmetic instructions that let you use the pointer to the array more flexibly:
p++ : This instruction increases the pointer so that it points to the next element of the array. If you followed it with
the instruction cout << *p; then it would display the number 2201, which is the contents of element v[1] (i.e. the
second element).
Similarly, you can use instructions such as += and -= to refer to different elements in the array:
p+=2;
p--;
You can even refer to the different array elements without having to alter the value of p. We have already used *p to
refer to the first element of the array (or subsequent elements if you have been updating p with += or -=), but you
can use *(p+1) to refer to the next element after *p, *(p+2) to refer to the one after that etc.