C++ #2 CH2
C++ #2 CH2
POINTERS
When we declare a variable some memory is allocated for it. The memory location
can be referenced through the identifier “i”. Thus, we have two properties for any
variable: its address and its data value. The address of the variable can be
accessed through the referencing operator “&”. “&i” gives the memory location
where the data value for “i” is stored.
A pointer is a variable whose value is the address of another variable. Like any
variable or constant, you must declare a pointer before you can work with it.
A pointer variable is one that stores an address. We can declare pointers as follows
int* p; .This means that p stores the address of a variable of type int.
type *var-name;
Here, type is the pointer's base type; it must be a valid C++ type and var-name is
the name of the pointer variable. The asterisk you used to declare a pointer is the
same asterisk that you use for multiplication. However, in this statement the
asterisk is being used to designate a variable as a pointer. Following are the valid
pointer declaration:
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.
1
This can be done by preceding the variable identifier by an ampersand sign (&), which
literally means "address of".
The address operator (&) returns the memory address of a variable.
Suppose the following variable is defined in a program:
float amount;
When the address operator (&) is placed in front of a variable name, it returns the address
of that variable. Here is an expression that returns the address of the variable amount:
&amount
And here is a statement that displays the variable’s address on the screen:
cout << &amount;
For example the statement:
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:
We have assigned to fred the content of variable andy, but to ted we have assigned the
address in memory where the operating system stores the value of andy, that we have
imagined was 1776. The reason is that in the allocation of ted we have preceded andy with
an ampersand (&) character.
The variable that stores the address of another variable (like ted in the previous example) is
what we call a pointer.
The following program segment demonstrates the use of the address operator to display the
address, size, and contents of a variable. It uses the & operator to determine a variable's
address and the sizeof operator to determine its size.
short x = 25;
cout << "The address of x is " << &x << endl;
cout << "The size of x is " << sizeof(x) << " bytes\n";
cout << "The value in x is " << x << endl;
2
Note: The address of the variable x is displayed in hexadecimal. This is the way addresses
are normally shown in C++.
Pointer Variables
Pointer variables, which are often just called pointers, are designed to hold memory
addresses. With pointer variables you can indirectly manipulate data stored in other variables.
Many operations are best performed with pointers, and some tasks aren’t possible without
them. They are very useful for things such as the following:
Working directly with memory locations that regular variables don’t give you access to
Working with strings and arrays
Creating new variables in memory while the program is running
Creating arbitrarily-sized lists of values in memory
Pointers are special variables that C++ provides for working with memory addresses. Just
like int variables are designed to hold and work with integers, pointer variables are designed
to hold and work with addresses.
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".
The definition of a pointer variable looks pretty much like any other definition. Here is an
example:
int *ptr;
The asterisk in front of the variable name indicates that ptr is a pointer variable. The int data
type indicates that ptr can be used to hold the address of an integer variable. The
declaration statement above would read “ptr is a pointer to an int.”
Note: In this definition, the word int does not mean that ptr is an integer variable. It means
that ptr can hold the address of an integer variable. Remember, pointers only hold one
thing: addresses.
Therefore, if we write:
andy = 25;
fred = andy;
ted = &andy;
beth = *ted;
beth would take the value 25, since ted is 1776, and the value pointed by 1776 is 25.
3
You must clearly differentiate 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:
beth = ted; // beth equal to ted ( 1776 )
beth = *ted; // beth equal to value pointed by ted ( 25 )
At this point, and following with the same example initiated above where:
andy = 25;
ted = &andy;
you should be able to clearly see that all the following expressions are true:
andy == 25
&andy == 1776
ted == 1776
*ted == 25
The first expression is quite clear considering that its assignation was andy=25;. The second
one uses the address (or deference) operator (&) that returns the address of the variable andy,
that we imagined to be 1776. The third one is quite obvious since the second was true and the
assignation of ted was ted = &andy;. The fourth expression uses the reference operator (*)
that, as we have just seen, is equivalent to the value contained in the address pointed by ted,
that is 25.
So, after all that, you may also infer that while the address pointed by ted remains unchanged
the following expression will also be true:
*ted == andy
4
DECLARING VARIABLES OF TYPE POINTER
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.
Another thing that can call your attention is the line:
int *p1, *p2;
that declares the two pointers of the previous example putting an asterisk (*) for each pointer.
In the following statements:
int x = 25;
int *ptr;
ptr = &x;
two variables are defined: x and ptr. The variable x is an int, while ptr is a pointer to an int. The
variable x is initialized with 25, while ptr is assigned the address of x with the following
statement:
ptr = &x;
The following figure illustrates the relationship between ptr and x.
As shown in the above figure, the variable x is located at memory address 0x7e00 and
contains the number 25, while the pointer ptr contains the address 0x7e00. In essence, ptr
“points” to the variable x.
The real benefit of pointers is that they allow you to indirectly access and modify the variable
being pointed to. In the above statements, for instance, ptr could be used to change the
contents of the variable x. This is done with the indirection operator, which is an asterisk (*).
When the indirection operator is placed in front of a pointer variable name, it dereferences
the pointer.
When you are working with a dereferenced pointer, you are actually working with the value
the pointer is pointing to.
Every time the expression *ptr appears in above statements, the program indirectly uses the
variable x.
int x = 25;
int *ptr;
5
ptr = &x;
The following cout statement displays the value in x twice:
cout << x << " " << *ptr << endl;
And the following statement stores 100 in x:
*ptr = 100;
With the indirection operator, ptr can be used to indirectly access the variable it is pointing
to.
Every time the expression *ptr appears in the above program segment, the program indirectly
uses the variable x. The following cout statement displays the value in x twice:
cout << x << " " << *ptr << endl;
And the following statement stores 100 in x:
*ptr = 100;
With the indirection operator, ptr can be used to indirectly access the variable it is pointing
to.
Pointers can point to different variables. For example:
int x = 25, y = 50, z = 75;
int *ptr;
ptr = &x; // Store the address of x in ptr
ptr = &y; // Now ptr store the address of y in ptr
ptr = &z; // Now ptr store the address of z in ptr
Note: So far you’ve seen three different uses of the asterisk in C++:
As the multiplication operator, in statements such as
distance = speed * time;
In the definition of a pointer variable, such as
int *ptr;
As the indirection operator, in statements such as
*ptr = 100;
An asterisk (*) followed by the pointer refers to the place pointed by the pointer, whereas a
pointer without an asterisk (*) refers to the value of the pointer itself, that is, the address of
where it is pointing.
POINTER INITIALIZATION
Pointers may be initialized with the address of an existing object.
Remember that a pointer is designed to point to an object of a specific data type.
When a pointer is initialized with an address, it must be the address of an object the pointer
can point to. For instance, the following definition of pint is legal because myValue is an
integer:
int myValue;
int *pint = &myValue;
The following is also legal because ages is an array of integers:
int ages[20];
int *pint = ages;
6
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 assignment 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.
POINTER ARITHMETIC
7
This is applicable both when adding and subtracting any number to a pointer. It would
happen exactly the same if we write:
mychar = mychar + 1;
myshort = myshort + 1;
mylong = mylong + 1;
It is important to warn you that both increase (++) and decrease (--) operators have a greater
priority than the reference operator asterisk (*), therefore the following expressions may lead
to confussion:
*p++;
*p++ = *q++;
The first one is equivalent to *(p++) and what it does is to increase p (the address where it
points to - not the value that contains).
In the second, because both increase operators (++) are after the expressions to be evaluated
and not before, first the value of *q is assigned to *p and then both q and p are increased by
one. It is equivalent to:
*p = *q;
p++;
q++;
Like always, I recommend you use parenthesis () in order to avoid unexpected results.
Examples on pointer
//how to use & and *
#include <iostream>
using namespace std;
int main()
{
int one = 10;
int *ptr1; // ptr1 is a pointer variable that points to an int
ptr1 = &one; // &one indicates that the address, not the
// contents, of one is being assigned to ptr1.
// Remember that ptr1 can only hold an address.
8
// Since ptr1 holds the address where the variable
// one is stored, we say that ptr1 "points to" one.
cout << "The value of one is " << one << endl << endl;
cout << "The value of &one is " << &one << endl << endl;
cout << "The value of ptr1 is " << ptr1 << endl << endl;
cout << "The value of *ptr1 is " << *ptr1 << endl << endl;
return 0;
}
Output Comments
The value of one is 10 //one is an integer variable, holding a 10.
The value of &one is 006AF0F4 //&one is the “address of” variable one.
The value of ptr1 is 006AF0F4 //ptr1 is assigned one’s address
The value of *ptr1 is 10 //* is the dereferencing operator which
means *ptr1 gives us the value of the
variable ptr1 is pointing at.
#include <iostream>
void main(void)
{
int x = 25, y = 50, z = 75;
int *ptr;
cout << "Here are the values of x, y, and z:\n";
cout << x << " " << y << " " << z << endl;
ptr = &x; // Store the address of x in ptr
*ptr *= 2; // Multiply value in x by 2
ptr = &y; // Store the address of y in ptr
*ptr *= 2; // Multiply value in y by 2
ptr = &z; // Store the address of z in ptr
*ptr *= 2; // Multiply value in z by 2
9
cout << "Once again, here are the values of x, y, and z:\n";
cout << x << " " << y << " " << z << endl;
}
// This program shows an array name being dereferenced
// with the * operator.
#include <iostream.h>
void main(void)
{
short numbers[] = {10, 20, 30, 40, 50};
cout << "The first element of the array is ";
cout << *numbers << endl;
}
void main(void)
{
int set[8] = {5, 10, 15, 20, 25, 30, 35, 40};
int *nums, index;
nums = set;
cout << "The numbers in set are:\n";
for (index = 0; index < 8; index++)
{
cout << *nums << " ";
++nums;
}
cout << "\nThe numbers in set backwards are:\n";
for (index = 0; index < 8; index++)
{
nums--;
cout << *nums << " ";
}
}
10
A pointer can be initialized during declaration by assigning it the address of an existing
variable
int *ip = 0;
float *fp = NULL;
The NULL pointer is a valid address for any data type.
11