ZeePedia

Pointers: Declaration of Pointers, Bubble Sort Example, Pointers and Call By Reference

<< Array Manipulation, Real World Problem and Design Recipe
Introduction, Relationship between Pointers and Arrays, Pointer Expressions and Arithmetic, Pointers Comparison, Pointer, String and Arrays >>
img
CS201 ­ Introduction to Programming
Lecture Handout
Introduction to Programming
Lecture No. 14
Reading Material
Deitel & Deitel - C++ How to Program
Chapter 5
5.1, 5.2, 5.3, 5.4,
5.5, 5.6
Summary
1)
Pointers
2)
Declaration of Pointers
3)
Example 1 (Bubble Sort)
4)
Pointers and Call By Reference
5)
Example 2
Pointers
In the earlier lectures, we had briefly referred to the concept of pointers. Let's see what a
pointer is and how it can be useful.
Pointers are a special type of variables in which a memory address is stored. They contain
a memory address, not the value of the variable. The concept of the pointers can be well
understood from the following example.
Suppose, we request someone to take a parcel to the house of a person, named Ahmad.
Here the point of reference is a name. However, if we specifically tell him the number of
house and the street number. Then this is a reference by the address of the house. It
means that we have two ways to locate an address. To understand further the concept of
memory address, the example of the computers can be helpful. In computers, one can
have a name x which is associated with a memory location. We can have the memory
address of x, say 6000 or whatever it is. So the simple variable names are those of
specific locations in memory. But in terms of addresses, these are the addresses of those
memory locations. We can use these names and addresses interchangeably to refer to
memory locations. When a value is referred by a normal variable is known as direct
reference. While the value referred through the use of memory address may be known as
indirect reference.
To understand further the terms of direct reference and indirect reference, suppose that
we want to assign a value 10 to x. This can be done by writing
x  =  10.  In  this
statement, the value 10 will be assigned to the memory location which has label (name) x.
The second way to assign a value to a memory location is with reference to the address of
Page 150
img
CS201 ­ Introduction to Programming
that memory location. In other words, `assign a value to the memory location whose
address is contained in the variable (that is a pointer) on right hand side of the assignment
operator'. Operators are used to refer the address of memory locations and to refer the
values at those addresses.
Following figure shows directly and indirectly referencing a variable.
x directly references
xptr indirectly references a variable whose
value is 10
xptr
x
a variable whose value is 10
x
10
10
Now we will try to comprehend the concept with another daily life example. Suppose,
hundreds of people are sitting in an auditorium. The host is going to announce a prize for
a person amongst the audience. There are two methods to call the prizewinner to dais.
The host can either call the name of the person or the number of the seat. These are
equivalent to `call by name' and `call by address' methods. In both cases, the prize will
be delivered to a person whether he is called by name or referred by address (seat number
in this case). In programming, pointers are used to refer by the addresses.
Declaration of Pointers
Pointers work by pointing to a particular data type. We can have pointer to an integer,
pointer to a double, pointer to a character and so on. It means that a type is associated to a
pointer. Pointer, being a variable, needs a name. The rules for naming a pointer are the
same as for the simple variable names. The pointers are declared in a specific way. The
syntax of declaring a pointer is:
data type *name ;
Here `name' is the name of the pointer and data type is the type of the data to which the
pointer (name) points. There is no space between asterisk (*) and the name. Each variable
being declared as a pointer must be preceded by *. The * is associated with the name of
the variable, not with the data type. To associate the * (asterisk) with data type (like int* )
may confuse the declaration statement. Suppose, we want to declare a pointer to an
integer. We will write as:
int *myptr;
Here myptr is the name of the pointer. The easiest way to understand the pointer
declaration line is the reading the statement from right to left. For the above statement,
we say that myptr is a pointer to an integer (int). Similarly for the declaration double *x ,
x is a pointer to a data of type double. The declaration of char *c shows that c is a pointer
to a data of type character. The declaration of multiple pointers requires the use of * with
each variable name. This is evident from the following example which declares three
Page 151
img
CS201 ­ Introduction to Programming
pointers.
int *ptr1, *ptr2, *ptr3 ;
Moreover, we can mix the pointers declaration with simple variables on one line.
int *ptr, x, a [10] ;
In this declaration ptr is a pointer to data of type int, x is a simple variable of type int and
a is an array of integers.
Whenever used, these pointers hold memory addresses.
Now we will try to understand what address a pointer holds. Suppose, we declare a
pointer variable ptr and a variable x and assign a value 10 to it. We write this as under.
int *ptr ;
int x ;
x = 10 ;
Here x is a name of a memory location where a value 10 is stored. We want to store the
address of this memory location (which is labeled as x) into the pointer ptr. To get the
address of x, we use address operator i.e. &. (it is & not &&, the && is logical AND). To
assign the address of x to pointer ptr, we write
ptr = &x ;
This statement assigns the memory address of the location x to the pointer ptr. The
following figure shows a schematic representation of memory after the preceding
assignment is executed.
x
ptr
1
The pointers contain whole numbers as they contain memory addresses. An address can
be represented only in whole numbers. Therefore, a pointer is a whole number, sufficient
enough, to hold any memory address of the computer. The pointers have no specific data
type.
In the above assignment statement, we have a pointer to a memory location. Now, it can
be ascertained what value is stored in that memory location. To get the value stored at a
memory address, we use the dereferencing operator, represented by asterisk (*). The * is
used with the name of the pointer to get the value stored at that address. To get the value
stored at the memory address ptr, we write *ptr which is read as the value of whatever ptr
points to. Thus the line z = *ptr; means, z has the value of whatever ptr points to.
The following example can explain the representation of the pointer in memory. Assume
that variable x is stored at location 400000 and pointer variable ptr is stored at location
Page 152
img
CS201 ­ Introduction to Programming
500000.
ptr
x
400000
10
Address:
500000
400000
We can use this operator (*) to get the value and can do any arithmetic operation with it.
The following statements make it further clear.
z = *ptr + 2 ;
z = *ptr * 2 ;
z = *ptr ­ 2 ;
Here *ptr gives the value stored at memory address where the pointer ptr points to.
We know that it is a good programming practice to initialize a variable when we declare
it. This will ensure that there will be no unknown value in the variable at some later
stage.
Similarly, we should assign an initial value to a pointer after declaring it. Taking the
address of a variable and assigning it to the pointer is one way of initializing a pointer. A
pointer can be initialized by assigning either value 0 or the word NULL. The NULL is a
global variable declared in many header files that we include at the start of the program.
The pointer initialized by NULL as ptr = NULL; is called null pointer which points to
nothing. Similarly, when we assign a zero to a pointer like ptr = 0; it means that the
pointer is pointing to nothing at the moment. Here zero is not considered as a valid
address for a memory location. However, at some later stage, we use the pointer in an
assignment statement either on left hand side to assign a value to it or as a part of an
expression on right hand side. The pointer must have a valid memory address where a
value should have stored. We get the address of a variable by putting & operator before
the name of the variable and assign it to a pointer as in the following statement ptr = &x;
We know that in C language, the default mechanism of function call is `call by value'.
Sometimes we want to make a call by reference. In call by reference, we pass the address
of the variable to a function by using & operator.
One of the major usages of pointers is to simulate call by reference while using it with
function calls. In the calling function, we pass the address of the variable to a function
being called by using & operator. We write a function call as fn( &x ) where &x indicates
that the address of variable x is being passed to the function fn. In the receiving function,
the function must know that the parameter passed to it is an address. So the declaration of
the receiving function will be as
void fn ( int *num)
{
Page 153
img
CS201 ­ Introduction to Programming
statement(s) ;
}
The int *num in the function declaration indicates that the receiving variable is a pointer
to a memory address. In the body of the function, we will use this variable as:
cin >> *num ;
This statement describes that the value entered through the keyboard (as cin is used) will
be stored at the memory address wherever the pointer num is pointing to.
While using value associated with the pointer, we write *num and &num in case of using
the address. This thing can be summarized as follows
"*num means the value of whatever the num points to and
&num means the address of the variable num"
The pointers can appear on the left hand side exactly like ordinary variables. In this case,
you would have an address statement on the right hand side. The address (operator (&) )
cannot be of an expression. Rather, it is always of a simple variable. We cannot write
&(x+y). The address (&) would be either of x (&x) or of y (&y). The address operator (&)
operates on a simple variable. Precisely speaking, whenever we have a pointer on left
hand side, the right hand side should have an address. If a pointer appears on the right
hand side of an expression, it can participate in any expression. In this case, we use the
operator * with the pointer name and get the value stored where the pointer points to.
Obviously we can do any calculation with this value (i.e. it can be used in any
expression).
Example (Bubble Sort)
You might be knowing the technique of bubble sorting. Its application helps us compare
two values each time and interchange the larger and smaller values. In this way, we sort
the arrays. To interchange the position of larger and smaller value, the technique of
swapping is used. Swapping is very common in programming. While using this
technique, we put value of one variable in a temporary location to preserve it and assign
the value of second variable to the first. Then the temporary value is assigned to the
second variable.
Suppose, we want to swap the values of two variables x and y. For this purpose, a third
variable temp is used in the following fashion.
temp = x ;
x=y;
y = temp ;
We can write the above three statements in a program to swap the value of x and y. Now
the question arises, can we call a function swap (x, y) which has a code to swap the
values of x and y. We call the function swap by passing x and y. When the control comes
back to the calling function, the values of x and y are the same as before. These are not
Page 154
img
CS201 ­ Introduction to Programming
swapped. This is mainly due to the fact that passing value to function swap is a call by
value. It does not change the values in the calling function. The swap function receives a
copy of the values and interchanges the values in that copy. The original values remain
the same.
To interchange two values in a function, we make a call by reference to the function.
Here comes the use of pointers. To write the swap function to interchange two values
always use pointers in the function to get the swapped values in the calling function. The
code fragment in our main program will be written as follows:
yptr = &y ;
// address of y is stored in yptr
xptr = &x ;
// address of x is stored in xptr
swap (yptr, xptr) ;
// addresses are passed
The receiving function must know that addresses are being passed to it. So the
declaration of swap function will be:
swap (int *yptr, int *xptr)
{
.........
}
This use of pointers implements a call by reference. We can use this technique in bubble
sort. The swap function can switch the elements of the array by using pointers and *
operator.
The code of the program that sorts an array by bubble sort and use the swap function to
interchange the elements of the array is given here.
/*
This program uses bubble sorting to sort a given array.
*
We use swap function to interchange the values by using pointers
*/
#include <iostream.h>
#include <stdlib.h>
/* Prototye of function swap used to swap two values */
void swap(int *, int *) ;
main()
{
int x [] = {1,3,5,7,9,2,4,6,8,10};
int i, j, tmp, swaps;
for(i = 0; i < 10; i ++)
{
swaps = 0;
for(j = 0; j < 10; j ++)
Page 155
img
CS201 ­ Introduction to Programming
{
if ( x[j] > x[j+1])
// compare two values and interchange if needed
{
swaps++;
swap(&x[j],&x[j+1]);
}
}
//display the array's elements after each comparison
for (j=0; j<10; j++)
cout << x[j] << '\t';
cout << endl;
if (swaps == 0)
break;
}
}
void swap(int *x, int *y)
//function using pointers to interchange the values
{
int tmp;
if(*x > *y)
{
tmp = *x;
*x = *y;
*y = tmp;
}
}
Following is the output of the program of bubble sort.
1
3
5
7
2
4
6
8
9
10
1
3
5
2
4
6
7
8
9
10
1
3
2
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
Pointers and Call By Reference
Suppose, we have a function that performs a specific task again and again but with
different variables each time. One way to do this is to pass a different variable to the
Page 156
img
CS201 ­ Introduction to Programming
function, each time, by reference. We can also write the function with pointers. In this
case, before calling the function, put the address of the simple variable in the pointer
variable and pass it to the function. This is a call by reference. Thus the same pointer
variable can be used each time by assigning it the address of a different variable.
The mechanism behind calling a function is that, when we call a function we pass it some
variables. The values of these variables are used with in the function. In call by value
mechanism, the values of these variables are written somewhere else in the memory. That
means a copy of these values is made. Then control goes to the called function and this
copy of values is used in the function. If we have to pass a huge number of values to a
function, it is not advisable to copy these huge numbers of values. In such cases, it is
better to pass the reference of the variables, which is a call by reference phenomenon. We
perform a similar function in case of an array, where we can pass, say, 100 values (size of
the array) to the called function, by only passing the name of the array. When we pass an
array to a function, actually the starting address of the array is passed to the function.
Thus the default calling mechanism to call a function while passing an array to it is a call
by reference.
The problem with call by reference is that `we are letting the function to change the
values at their actual storage place in the memory'. Sometimes, we want to do this
according to the requirement of the logic of the program. At some other occasion, we
may pass the addresses for efficiency while not affecting the values at that addresses. The
use of const can be helpful in overcoming this problem..
Let's look at the use of const. Consider the following line of declaration:
int *const myptr = &x ;
The right hand side of this assignment statement could be read as, myptr is a constant
pointer to an integer. Whenever we use the keyword const with a variable, the value of
that variable becomes constant and no other value can be assigned to it later on. We know
that when we declare a constant variable like const int x ; it is necessary to assign a value
to x and we write const int x = 10 . After this, we cannot assign some other value to x.
The value of x can not be changed as it is declared as a constant.
Now consider the previous statement
int *const myptr = &x ;
Here we declare a constant pointer to an integer. Being a constant pointer, it should
immediately point to something. Therefore, we assign this pointer an address of a
variable x at the time of declaration. Now this pointer cannot be changed. The pointer
myptr will hold the address of variable x throughout the program. This way, it becomes
just another name for the variable x. The use of constant pointers is not much useful.
The use of keyword const in declaration statement is a little tricky. The statement
int *const myptr = &x ;
means myptr is a constant pointer to an integer. But if we change the place of const in this
statement and write
Page 157
img
CS201 ­ Introduction to Programming
const int *myptr = &x ;
This statement describes that myptr is a pointer to a constant integer. This means that the
value of pointer myptr can be changed but the value stored at that location cannot be
changed. This declaration is useful. It has a common use in call by reference mechanism.
When we want to pass the arguments to a function by reference without changing the
values stored at that addresses. Then we use this construct of declaration (i.e. const int
*myptr) in the called function declaration. We write the declaration of the function like
fn ( const int *myptr)
{
....
}
This declaration informs the function that the receiving value is a constant integer. The
function cannot change this value. Thus we can use the address of that value for
manipulations but cannot change the value stored at that location.
Example 2
Let's consider an example in which we use the pointers to make a call by reference.
We want to convert the lowercase letters of a string (character array), to their
corresponding uppercase letters.
We write a function convertToUppercase, which processes the string s one character at a
time using pointer arithmetic. In the body of the function, we pass the character to a
function islower. This function returns true if the character is a lowercase letter and false
otherwise. The characters in the range `a' through `z' are converted to their
corresponding uppercase letters by function toupper. Function toupper takes one
character as an argument. If the character is a lowercase letter, the corresponding
uppercase letter is returned, otherwise the original character is returned. The functions
toupper and islower are part of the character handling library <ctype.h>. So we have to
include this header file in our program. We include it in the same way, as we include
<iostream.h>.
The complete code of the program is given below.
//This program converts a string into an uppercase string
# include <iostream.h>
# include <ctype.h>
# include <stdlib.h>
//declare the functions prototype
void convertToUppercase (char *)
main ()
{
Page 158
img
CS201 ­ Introduction to Programming
char s [30] = "Welcome To Virtual University" ;
cout << "The string before conversion is: " << s << endl ;
convertToUppercase ( s) ;
//function call
cout << "The string after conversion is: " << s ;
}
void convertToUppercase (char *sptr)
{
while ( *sptr != `\0' )
{
if ( islower ( *sptr) )
*sptr = toupper ( *sptr );
//convert to uppercase
++ sptr;
// move sptr to the next
character
}
}
Following is the output of the program.
The string before conversion is :
Welcome To
The string after conversion is :
WELCOME TO
Exercise
1.
Modify the above program so that it gets a string from user and converts it into
lowercase.
2.
Write a program, which converts a string of uppercase letters into its corresponding
lowercase letters string.
Page 159
Table of Contents:
  1. What is programming
  2. System Software, Application Software, C language
  3. C language: Variables, Data Types, Arithmetic Operators, Precedence of Operators
  4. C++: Examples of Expressions, Use of Operators
  5. Flow Charting, if/else structure, Logical Operators
  6. Repetition Structure (Loop), Overflow Condition, Infinite Loop, Properties of While loop, Flow Chart
  7. Do-While Statement, for Statement, Increment/decrement Operators
  8. Switch Statement, Break Statement, Continue Statement, Rules for structured Programming/Flow Charting
  9. Functions in C: Structure of a Function, Declaration and Definition of a Function
  10. Header Files, Scope of Identifiers, Functions, Call by Value, Call by Reference
  11. Arrays: Initialization of Arrays, Copying Arrays, Linear Search
  12. Character Arrays: Arrays Comparisonm, Sorting Arrays Searching arrays, Functions arrays, Multidimensional Arrays
  13. Array Manipulation, Real World Problem and Design Recipe
  14. Pointers: Declaration of Pointers, Bubble Sort Example, Pointers and Call By Reference
  15. Introduction, Relationship between Pointers and Arrays, Pointer Expressions and Arithmetic, Pointers Comparison, Pointer, String and Arrays
  16. Multi-dimensional Arrays, Pointers to Pointers, Command-line Arguments
  17. String Handling, String Manipulation Functions, Character Handling Functions, String Conversion Functions
  18. Files: Text File Handling, Output File Handling
  19. Sequential Access Files, Random Access Files, Setting the Position in a File, seekg() and tellg() Functions
  20. Structures, Declaration of a Structure, Initializing Structures, Functions and structures, Arrays of structures, sizeof operator
  21. Bit Manipulation Operators, AND Operator, OR Operator, Exclusive OR Operator, NOT Operator Bit Flags Masking Unsigned Integers
  22. Bitwise Manipulation and Assignment Operator, Programming Constructs
  23. Pre-processor, include directive, define directive, Other Preprocessor Directives, Macros
  24. Dynamic Memory Allocation, calloc, malloc, realloc Function, Dangling Pointers
  25. History of C/C++, Structured Programming, Default Function Arguments
  26. Classes and Objects, Structure of a class, Constructor
  27. Classes And Objects, Types of Constructors, Utility Functions, Destructors
  28. Memory Allocation in C++, Operator and Classes, Structures, Function in C++,
  29. Declaration of Friend Functions, Friend Classes
  30. Difference Between References and Pointers, Dangling References
  31. Operator Overloading, Non-member Operator Functions
  32. Overloading Minus Operator, Operators with Date Class, Unary Operators
  33. Assignment Operator, Self Assignmentm, Pointer, Conversions
  34. Dynamic Arrays of Objects, Overloading new and delete Operators
  35. Source and Destination of streams, Formatted Input and Output, Buffered Input/Output
  36. Stream Manipulations, Manipulators, Non Parameterized Manipulators, Formatting Manipulation
  37. Overloading Insertion and Extraction Operators
  38. User Defined Manipulator, Static keyword, Static Objects
  39. Pointers, References, Call by Value, Call by Reference, Dynamic Memory Allocation
  40. Advantages of Objects as Class Members, Structures as Class Members
  41. Overloading Template Functions, Template Functions and Objects
  42. Class Templates and Nontype Parameters, Templates and Static Members
  43. Matrices, Design Recipe, Problem Analysis, Design Issues and Class Interface
  44. Matrix Constructor, Matrix Class, Utility Functions of Matrix, Input, Transpose Function
  45. Operator Functions: Assignment, Addition, Plus-equal, Overloaded Plus, Minus, Multiplication, Insertion and Extraction