Lab: Title: Lab Objectives:: Pointer Variables

Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

LAB: 7

Title : Pointers
Lab Objectives:  To introduce pointer variables and their relationship with arrays
 To introduce the dereferencing operator
 To introduce the concept of dynamic memory allocation
Pre-Lab Reading:
Pointer Variables

A distinction must always be made between a memory location’s address and the data stored at that
location. A street address like “King Gorge St.” is a location that is different than a description of
what is at that location: “The main campus of Addis Ababa University”. So far we have been
concerned only with the data stored in a variable, rather than with its address (where in main memory
the variable is located). In this lab we will look at addresses of variables and at special variables,
called pointers, which hold these addresses. The address of a variable is given by preceding the
variable name with the C++ address operator (&):

cout << &sum; // This outputs the address of the variable sum

The & operator in front of the variable sum indicates that the address itself, and not the data stored
in that location, is the value used. On most systems the above address will print as a hexadecimal
value representing the physical location of the variable. Before this lesson where have you used the
address operator in C++ programming? You may recall that it was used in the prototype and the
function heading of a function for parameters being passed by reference. This connection will be
explored in the next section.

To define a variable to be a pointer, we precede it with an asterisk (*):

int *ptr;

The asterisk in front of the variable indicates that ptr holds the address of a memory location. The
int indicates that the memory location that ptr points to holds integer values. ptr is NOT an
integer data type, but rather a pointer that holds the address of a location where an integer value is
stored. This distinction is most important!

The following example illustrates this difference.


int sum; // sum holds an integer value.
int *sumPtr; // sumPtr holds an address where an
// integer can be found.

By now there may be confusion between the symbols * and &, so we next discuss their use.

1
Using the & Symbol

The & symbol is basically used on two occasions

1. The most frequent use we have seen is between the data type and the variable name of a pass
by reference parameter in a function heading/prototype. This is called a reference variable.
The memory address of the parameter is sent to the function instead of the value at that
address. When the parameter is used in the function, the compiler automatically
dereferences the variable. Dereference means that the location of that reference variable
(parameter in this case) is accessed to retrieve or store a value.

We have looked at the swap function on several occasions. We revisit this routine to show
that the & symbol is used in the parameters that need to be swapped. The reason is that these
values need to be changed by the function and, thus, we give the address (location in
memory) of those values so that the function can write their new values into them as they are
swapped.

Example:

void swap(int &first, int &second)


{ // The & indicates that the parameters
// first and second are being passed by
// reference.

int temp;

temp = first; // Since first is a reference variable,


// the compiler retrieves the value
// stored there and places it in temp.

first = second // New values are written directly into


second = temp; // the memory locations of first and second.

2. The & symbol is also used whenever we are interested in the address of a variable rather than
its contents.

cout << sum; // This outputs the value stored in the


// variable sum.
cout << &sum; // This outputs the address where
// sum is stored in memory.

Using the & symbol to get the address of a variable comes in handy when we are assigning values
to pointer variables.

2
Using the * Symbol

The * symbol is also basically used on two occasions.

1. It is used to define pointer variables:

int *ptr;

2. It is also used whenever we are interested in the contents of the memory location pointed to
by a pointer variable, rather than the address itself. When used this way * is called the
indirection operator, or dereferencing operator.

Example:

cout << *ptr; // Since ptr is a pointer variable, *


// dereferences ptr. The value stored at the
// location ptr points to will be printed.

Using * and & Together

In many ways * and & are the opposites of each other. The * symbol is used just before a pointer
variable so that we may obtain the actual data rather than the address of the variable. The & symbol
is used on a variable so that the variable’s address, rather than the data stored in it, will be used. The
program in file:lab7sample.cpp demonstrates the use of pointers.

What do you expect will be printed if the address of variable one is the hexadecimal value
006AFOF4? The following will be printed by the program.

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.

Arrays and Pointers

When arrays are passed to functions they are passed by pointer. An array name is a pointer to the
beginning of the array. Variables can hold just one value and so we can reference that value by just
naming the variable. Arrays, however, hold many values. All of these values cannot be referenced
just by naming the array. This is where pointers enter the picture. Pointers allow us to access all the
array elements. Recall that the array name is really a pointer that holds the address of the first element
in the array. By using an array index, we dereference the pointer which gives us the contents of that
array location. If grades is an array of 5 integers, as shown below, grades is actually a pointer

3
to the first location in the array, and grades[0] allows us to access the contents of that first
location.

From the last section we know it is also possible to dereference the pointer by using the * operator.
What is the output of the following two statements?
cout << grades[0]; // Output the value stored in the 1st array element
cout << *grades; // Output the value found at the address stored
// in grades (i.e., at the address of the 1st array
// element).

Both statements are actually equivalent. They both print out the contents of the first grades array
location, a 90.

Access of an individual element of an array through an index is done by pointer arithmetic. We


can access the second array location with grades[1], the third location with grades[2], and
so on, because the indices allow us to move through memory to other addresses relative to the
beginning address of the array. The phrase “address + 1” in the previous diagram means to move
one array element forward from the staring address of the array. The third element is accessed by
moving 2 elements forward and so forth. The amount of movement in bytes depends on how much
memory is allocated for each element, and that depends on how the array is defined. Since grades
is defined as an array of integers, if an integer is allocated 4 bytes, then +1 means to move forward
4 bytes from the starting address of the array, +2 means to move forward 8 bytes, etc. The compiler
keeps track of how far forward to move to find a desired element based on the array index. Thus the
following two statements are equivalent.

cout << grades[2];


cout << *(grades + 2);

Both statements refer to the value located two elements forward from the starting address of the
array. Although the first may be the easiest, computer scientists need to understand how to access
memory through pointers. The program in file:lab7sample2.cpp illustrates how to use pointer
arithmetic rather than indexing to access the elements of an array.

What is printed by the program?


The first grade is 90
The second grade is 88
The third grade is 76
The fourth grade is 54
The fifth grade is 34

4
Dynamic Variables

In our lab on arrays, we saw how the size of an array is given at the time of its definition. The
programmer must estimate the maximum number of elements that will be used by the array and this
size is static, i.e., it cannot change during the execution of the program. Consequently, if the array
is defined to be larger than is needed, memory is wasted. If it is defined to be smaller than is needed,
there is not enough memory to hold all of the elements. The use of pointers (and the new and
delete operators described below) allows us to dynamically allocate enough memory for an array
so that memory is not wasted.

This leads us to dynamic variables. Pointers allow us to use dynamic variables, which can be
created and destroyed as needed within a program. We have studied scope rules, which define where
a variable is active. Related to this is the concept of lifetime, the time during which a variable exists.
The lifetime of dynamic variables is controlled by the program through explicit commands to
allocate (i.e., create) and deallocate (i.e., destroy) them. The operator new is used to allocate and the
operator delete is used to deallocate dynamic variables. The compiler keeps track of where in
memory non-dynamic variables (variables discussed thus far in this book) are located. Their contents
can be accessed by just naming them. However, the compiler does not keep track of the address of
a dynamic variable. When the new command is used to allocate memory for a dynamic variable, the
system returns its address and the programmer stores it in a pointer variable. Through the pointer
variable we can access the memory location.

Example:

int *one; // one and two are defined to be pointer


int *two; // variables that point to ints
int result; // defines an int variable that will hold
// the sum of two values.
one = new int; // These statements each dynamically
two = new int; // allocate enough memory to hold an int
// and assign their addresses to pointer
// variables one and two, respectively.
*one = 10; // These statements assign the value 10
*two = 20; // to the memory location pointed to by one
// and 20 to the memory location pointed to
// by two.

result = *one + *two;


// This adds the contents of the memory
// locations pointed to by one and two.
cout << "result = " << result << endl;

delete one; // These statements deallocate the dynamic


delete two; // variables. Their memory is freed and
// they cease to exist.

5
Now let us use dynamic variables to allocate an appropriate amount of memory to hold an array.
By using the new operator to create the array, we can wait until we know how big the array needs
to be before creating it. The program in file: lab7sample3.cpp demonstrates this idea. First the user
is asked to input the number of grades to be processed. Then that number is used to allocate exactly
enough memory to hold an array with the required number of elements for the grades.
Notice how the dynamic array is passed as a parameter to the sortIt and displayGrades
functions. In each case, the call to the function simply passes the name of the array, along with its
size as an argument. The name of the array holds the array’s starting address.

sortIt(grades, numOfGrades);

In the function header, the formal parameter that receives the array is defined to be a pointer data
type.

void sortIt(float* grades, int numOfGrades)

Since the compiler treats an array name as a pointer, we could also have written the following
function header.

void sortIt(float grades[], int numOfGrades)

In this program, dynamic allocation of memory was used to save memory. This is a minor
consideration for the type of programs done in this course, but a major concern in professional
programming environments where large fluctuating amounts of data are used.

Review of * and &

The * symbol is used to define pointer variables. In this case it appears in the variable definition
statement between the data type and the pointer variable name. It indicates that the variable holds
an address, rather than the data stored at that address.

Example 1: int *ptr1;

* is also used as a dereferencing operator. When placed in front of an already defined pointer
variable, the data stored at the location the pointer points to will be used and not the address.

Example 2: cout << *ptr1;

Since ptr1 is defined as a pointer variable in Example 1, if we assume ptr1 has now been assigned
an address, the output of Example 2 will be the data stored at that address. * in this case
dereferences the variable ptr1.

The & symbol is used in a procedure or function heading to indicate that a parameter is being
passed by reference. It is placed between the data type and the parameter name of each parameter
that is passed by reference.

6
The & symbol is also used before a variable to indicate that the address, not the contents, of the
variable is to be used.

Example 3:
int *ptr1;
int one = 10;
ptr1 = &one; // This assigns the address of variable
// one to ptr1

cout << "The value of &one is "


<< &one << endl;
// This prints an address

cout << "The value of *ptr1 is "


<< *ptr1 << endl;
// This prints 10, because ptr1 points
// to one and * is the dereferencing
// operator.

7
Pre-lab
1. The ____________________ symbol is the dereferencing operator.

2. The ____________________ symbol means “address of.”

3. The name of an array, without any brackets, acts as a(n) __________________ to the
starting address of the array.

4. An operator that allocates a dynamic variable is __________________.

5. An operator that deallocates a dynamic variable is __________________.

6. Parameters that are passed by _______________ are similar to a pointer variable in that
they can contain the address of another variable. They are used as parameters of a
procedure (void function) whenever we want a procedure to change the value of the
argument.

Given the following information, fill the blanks with either “an address” or “3.75”.

float * pointer;
float pay = 3.75;
pointer = &pay;

7. cout << pointer; will print ___________________ .

8. cout << *pointer; will print ________________ .

9. cout << &pay; will print __________________ .

10. cout << pay; will print ___________________.

8
Lab 1: Introduction to Pointer Variables
Retrieve program lab7a.cpp from the exercises directory in lab 7 and perform the tasks:

Exercise 1: Complete this program by filling in the code. Note: use only pointer variables
when instructed to by the comments with three forward slash. This program is to test your
knowledge of pointer variables and the & and * symbols.

Exercise 2: Run the program with the following data: 10 15. Record the output here
___________.

Lab 2: Dynamic Memory


Retrieve program lab7b.cpp from the exercises directory in lab 7 and perform tasks:

Exercise 1: Complete the program by filling in the code. This problem requires that you
study very carefully the code already written to prepare you to complete the program.

Sample Run:
Enter your last name with exactly 10 characters.
If your name < 10 characters, repeat last letter. Blanks do not count.
DeFinooooo
Hi DeFinooooo
Enter three integer numbers separated by blanks
5 6 7
The three numbers are 5 6 7
The sum of the three values is 18

Exercise 2: In inputting and outputting the name, you were asked NOT to use a bracketed
subscript. Why is a bracketed subscript unnecessary?

Would using name[pos] work for inputting the name? Why or why not?
Would using name[pos] work for outputting the name? Why or why not?
Try them both and see.

Lab 3: Dynamic Arrays


Retrieve program lab7c.cpp from the exercises directory in lab 7 and perform the following tasks.

Exercise 1: Fill in the code as indicated by the comments in bold.

Sample Run:
How many monthly sales will be processed 3
Enter the sales below
Sales for Month number 1: 401.25
Sales for Month number 2: 352.89
Sales for Month number 3: 375.05
Average Monthly sale is $376.40

9
Lab 4: Print the address
Retrieve program lab7d.cpp from the exercises directory in lab 7 and introduce int variables x
and y and int* pointer variables p and q. Set x to 2, y to 8, p to the address of x, and q to the
address of y. Then write a code to print the following information, but before executing the
program write down the outputs you expect from each of this statements. After executing the
program compare the actual output with your expectation

1. The address of x and the value of x.


2. The value of p and the value of *p.
3. The address of y and the value of y.
4. The value of q and the value of *q.
5. The address of p (not its contents!).
6. The address of q (not its contents!).

Lab 5: Address Manipulations I


Retrieve program lab7e.cpp from the exercises directory in lab 7 and introduce int variables x,
y, z and int* pointer variables p, q, r. Set x, y, z to three distinct values. Set p, q,
r to the addresses of x, y, z respectively. Then write a code to perform the following tasks, but
before executing the program write down the outputs you expect from each of this statements.
After executing the program compare the actual output with your expectation.

1. Print with labels the values of x, y, z, p, q, r, *p, *q, *r.


2. Print the message: Swapping values.
3. Execute the swap code: z = x; x = y; y = z;
4. Print with labels the values of x, y, z, p, q, r, *p, *q, *r.

Lab 6: Address Manipulations II


Retrieve program lab7f.cpp from the exercises directory in lab 7 and introduce int variables x,
y, z and int* pointer variables p, q, r. Set x, y, z to three distinct values. Set p, q,
r to the addresses of x, y, z respectively. . Then write a code to perform the following tasks,
but before executing the program write down the outputs you expect from each of this statements.
After executing the program compare the actual output with your expectation.

1. Print with labels the values of x, y, z, p, q, r, *p, *q, *r.


2. Print the message: Swapping pointers.
3. Execute the swap code: r = p; p = q; q = r;
4. Print with labels the values of x, y, z, p, q, r, *p, *q, *r.

Paper-and-pencil-exercise: Draw diagrams to explain the results of Lab 5 and 6.

10
Lab 7: Address Manipulations III
Retrieve program lab7g.cpp from the exercises directory in lab 7 and introduce 4 int variables
and one array variable a as follows:
int x = 11;
int y = 12;
int a[5];
int u = 31;
int v = 32;
Then:
1. Write a loop to fill the array a with 21, 22, 23, 24, 25.
2. Execute the following loop:

Note: The above loop represents very bad practice since it accesses two cells before the start of
the array and two cells after it. The loop shows that you will access adjacent memory and that
C++ gives no direct protection against such memory access errors.

Lab 8: Address Manipulations II


Retrieve program lab7h.cpp from the exercises directory in lab 7 and define an array int a[5]
and fill this array with values 1, 4, 7, 10, 13. Introduce an int i and an int* pointer variable
p. Then run two printing loops:

for (i = 0; i < 5; i++)


cout << i << " " << Hex(a+i) << " " << a[i] << endl;

cout << endl;


i = 0;
p = a;

while (p < (a+5)) {


cout << i << " " << Hex(p) << " " << *p << endl;
i++;
p++;
}

Lab 9: Address Manipulations II


Retrieve program lab7i.cpp from the exercises directory in lab 7 and define an int* pointer
variable a. Then:
1. Use new to make a point to a dynamic array of 5 cells of type int.
2. Write a loop to fill a with values 3, 7, 11, 15, 19.
3. Print the pointer address stored in a.
4. Write a loop to print the values in a with one cell per line.
5. Delete the dynamic memory allocated to a using delete [ ].

11
12
Lab Assignments:
1. Sorted Scores
Write a program that will read scores into an array. The size of the array should be input by the
user (dynamic array). The program will find and print out the average of the scores. It will also
call a function that will sort the scores in ascending order. The values are then printed in this sorted
order. Use file lab7assignment1.cpp to test and submit your solution.

Sample Run:

Please input the number of scores


5
Please enter a score
100
Please enter a score
90
Please enter a score
95
Please enter a score
100
Please enter a score
90
The average of the scores is 95

Here are the scores in ascending order


90
90
95
100
100

2. Search Id
This program will read in id numbers and place them in an array. The array is dynamically
allocated large enough to hold the number of id numbers given by the user. The program will then
input an id and call a function to search for that id in the array. It will print whether the id is in the
array or not. Use file lab7assignment2.cpp to test and submit your solution.

Sample Run:

Please input the number of id numbers to be read


4
Please enter an id number
96
Please enter an id number
97
Please enter an id number
98
Please enter an id number

13
99

Please input an id number to be searched


67
67 is not in the array

3. Total Sales
Write a program that will read monthly sales into a dynamically allocated array. The program will
input the size of the array from the user. It will call a function that will find the yearly sum (the
sum of all the sales). It will also call another function that will find the average. Use file
lab7assignment3.cpp to test and submit your solution.

Sample Run:
Please input the number of monthly sales to be input
4
Please input the sales for month 1
1290.89
Please input the sales for month 2
905.95
Please input the sales for month 3
1567.98
Please input the sales for month 4
994.83
The total sales for the year is $4759.65
The average monthly sale is $1189.91

14

You might also like