You are on page 1of 6

Introduction to Computing

Fall 14

We have already seen how variables are memory cells that we can access by an identifier. But these variables
are stored in concrete places of the computer memory. For our programs, the computer memory is only a
succession of 1 byte cells (the minimum size for a datum), each one with a unique address.

A good simile for the computer memory can be a street in a city. On a street all houses are consecutively
numbered with an unique identifier so if we talk about 27th of Sesame Street we will be able to find that place
without trouble, since there must be only one house with that number and, in addition, we know that the
house will be between houses 26 and 28.

In the same way in which houses in a street are numbered, the operating system organizes the memory with
unique and consecutive numbers, so if we talk about location 1776 in the memory, we know that there is only
one location with that address and also that is between addresses 1775 and 1777.

Address Operator (&)


At the moment in which we declare a variable it must be stored in a concrete location in this succession of
cells (the memory). We generally do not decide where the variable is to be placed - fortunately that is
something automatically done by the compiler and the operating system at runtime, but once the operating
system has assigned an address there are some cases in which we may be interested in knowing where the
variable is stored.

This can be done by preceding the variable identifier by an ampersand sign (&), which literally means
"address of". For example:

ted = &andy;

would assign to variable ted the address of variable andy, since when preceding the name of the variable
andy with the ampersand (&) character we are no longer talking about the content of the variable, but about
its address in memory.

We are going to suppose that andy has been placed in the memory address 1776 and that we write the
following:

andy = 25;
fred = andy;
ted = &andy;

the result is shown in the following diagram:


Reference Operator (*)
Using a pointer we can directly access the value stored in the variable pointed by it just by preceding the
pointer identifier with the reference operator asterisk (*), that can be literally translated to "value pointed
by". Therefore, following with the values of the previous example, if we write:

beth = *ted;

(that we could read as: "beth equal to value pointed by ted") beth would take the value 25, since ted is
1776, and the value pointed by 1776 is 25.

You must clearly differenciate that ted stores 1776, but *ted (with an asterisk * before) refers to the value
stored in the address 1776, that is 25. Notice the difference of including or not including the reference
asterisk (I have included an explanatory commentary of how each expression could be read):

beth = ted; // beth equal to ted ( 1776 )


beth = *ted; // beth equal to value pointed by ted ( 25 )

You should be able to clearly see that all the following expressions are true:

andy == 25
&andy == 1776
ted == 1776
*ted == 25

Pointer Declaration
Due to the ability of a pointer to directly reference the value that it point to, it becomes necessary to specify
which data type a pointer points to when declaring it. It is not the same to point to a char as it is to point to
an int or a float type.

Therefore, the declaration of pointers follows this form:

type * pointer_name;

where type is the type of data pointed, not the type of the pointer itself. For example:
int * number;
char * character;
float * greatnumber;
they are three declarations of pointers. Each one points to a different data type, but the three are pointers and
in fact the three occupy the same amount of space in memory (the size of a pointer depends on the operating
system), but the data to which they point do not occupy the same amount of space nor are of the same type,
one is int, another one is char and the other one float.

I emphasize that the asterisk (*) that we use when declaring a pointer means only that it is a pointer, and
should not be confused with the reference operator that we have seen a bit earlier which is also written with
an asterisk (*). They are simply two different tasks represented with the same sign.

Sample Program1
// my first pointer
#include <iostream.h>

int main ()
{
int value1 = 5, value2 = 15;
int * mypointer;

mypointer = &value1;
*mypointer = 10;
mypointer = &value2;
*mypointer = 20;
cout << "value1==" << value1 << "/ value2==" << value2;
return 0;
}

Sample Program2
// more pointers
#include <iostream.h>

int main ()
{
int value1 = 5, value2 = 15;
int *p1, *p2;

p1 = &value1; // p1 = address of value1


p2 = &value2; // p2 = address of value2
*p1 = 10; // value pointed by p1 = 10
*p2 = *p1; // value pointed by p2 = value pointed by p1
p1 = p2; // p1 = p2 (value of pointer copied)
*p1 = 20; // value pointed by p1 = 20

cout << "value1==" << value1 << "/ value2==" << value2;
return 0;
}

Pointers and Arrays


The concept of array is very much bound to the one of pointer. In fact, the identifier of an array is equivalent
to the address of its first element, like a pointer is equivalent to the address of the first element that it points
to, so in fact they are the same thing. For example, supposing these two declarations:

int numbers [20];


int * p;

the following allocation would be valid:


p = numbers;

At this point p and numbers are equivalent and they have the same properties, the only difference is that we
could assign another value to the pointer p whereas numbers will always point to the first of the 20 integer
numbers of type int with which it was defined. So, unlike p, that is an ordinary variable pointer, numbers is a
constant pointer (indeed an array name is a constant pointer). Therefore, although the previous expression
was valid, the following allocation is not:

numbers = p;

because numbers is an array (constant pointer), and no values can be assigned to constant identifiers.

Due to the character of variables all the expressions that include pointers in the following example are
perfectly valid:

// more pointers
#include <iostream.h>

int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}

Pointer Initialization
When declaring pointers we may want to explicitly specify to which variable we want them to point,

int number;
int *tommy = &number;

this is equivalent to:

int number;
int *tommy;
tommy = &number;

When a pointer assignation takes place we are always assigning the address where it points to, never the value
pointed. You must consider that at the moment of declaring a pointer, the asterisk (*) indicates only that it is
a pointer, it in no case indicates the reference operator (*). Remember, they are two different operators,
although they are written with the same sign. Thus, we must take care not to confuse the previous with:

int number;
int *tommy;
*tommy = &number;
that anyway would not have much sense in this case.
As in the case of arrays, the compiler allows the special case that we want to initialize the content at which
the pointer points with constants at the same moment as declaring the variable pointer:

char * terry = "hello";

in this case static storage is reserved for containing "hello" and a pointer to the first char of this memory
block (that corresponds to 'h') is assigned to terry. If we imagine that "hello" is stored at addresses 1702
and following, the previous declaration could be outlined thus:

it is important to indicate that terry contains the value 1702 and not 'h' nor "hello", although 1702
points to these characters.

The pointer terry points to a string of characters and can be used exactly as if it was an Array (remember
that an array is just a constant pointer). For example, if our temper changed and we wanted to replace the
'o' by a '!' sign in the content pointed by terry, we could do it by any of the following two ways:

terry[4] = '!';
*(terry+4) = '!';

remember that to write terry[4] is just the same as to write *(terry+4), although the most usual
expression is the first one. With either of those two expressions something like this would happen:

Arithmetic of Pointers
To conduct arithmetical operations on pointers is a little different than to conduct them on other integer data
types. To begin with, only addition and subtraction operations are allowed to be conducted, the others make
no sense in the world of pointers. But both addition and subtraction have a different behavior with pointers
according to the size of the data type to which they point.

When we saw the different data types that exist, we saw that some occupy more or less space than others in
the memory. For example, in the case of integer numbers, char occupies 1 byte, short occupies 2 bytes and
long occupies 4.

Let's suppose that we have 3 pointers:


char *mychar;
short *myshort;
long *mylong;

and that we know that they point to memory locations 1000, 2000 and 3000 respectively.

So if we write:

mychar++;
myshort++;
mylong++;

You might also like