<Previous Lesson

Introduction to Programming

Next Lesson>

Lesson#15

Lesson 15

Summary

 

6) Introduction
7) Relationship between Pointers and Arrays
8) Pointer Expressions and Arithmetic
9) Pointers Comparison
10) Pointer, String and Arrays
11) Tips
Introduction

In the previous lecture, we had just started the discussion on the topic of pointers. This
topic is little complicated, yet the power we get with the pointers is very interesting. We
can do many interesting things with pointers. When other languages like Java evolve with
the passage of time, pointers are explicitly excluded. In today’s lecture, we will discuss
pointers, the relationship between pointers and arrays, pointer expressions, arithmetic
with pointers, relationship between arrays and pointer, strings etc.
Relationship between Pointers and Arrays

When we write int x, it means that we have attached a symbolic name x, at some memory
location. Now we can use x = 10 which replaces the value at that memory location with
10. Similarly while talking about arrays, suppose an array as int y[10]. This means that
we have reserved memory spaces for ten integers and named it collectively as y. Now we
will see what actually y is? 'y' represents the memory address of the beginning of this
collective memory space. The first element of the array can be accessed as y[0].
Remember arrays index starts from 0 in C language, so the memory address of first
element i.e. y[0] is stored in y.
“The name of the array is a constant pointer which contains the memory address
of the first element of the array”
Page 161
The difference between this and an ordinary pointer is that the array name is a constant
pointer. It means that the array name will always point to the start of the array. In other
words, it always contains the memory address of the first element of the array and cannot
be reassigned any other address. Let's elaborate the point with the help of following
example.
int y[10];
int *yptr;
In the above statements, we declare an array y of ten integers and a pointer to an integer
i.e. yptr. This pointer may contain a memory address of an integer.
yptr = y;
This is an assignment statement. The value of y i.e. the address of the first element of the
array is assigned to yptr. Now we have two things pointing to the same place, y and yptr.
Both are pointing to the first element of the array. However, y is a constant pointer and
always points to the same location whereas yptr is a pointer variable that can also point to
any other memory address.

Pointer Expressions and Arithmetic


Suppose we have an array y and yptr, a pointer to array. We can manipulate arrays with
both y and yptr. To access the fourth element of the array using y, we can say y[3]; with
yptr,
we can write as *(yptr + 4). Now we have to see what happens when we increment
or add something to a pointer. We know that y is a constant pointer and it can not be
incremented. We can write y[0], y[1] etc. On the other hand, yptr is a pointer variable
and can be written as the statement yptr = y. It means that yptr contains the address of the
first element of the array. However, when we say yptr++, the value of yptr is
incremented. But how much? To explain it further, we increment a normal integer
variable like x++. If x contains 10, it will be incremented by 1 and become 11. The
increment of a pointer depends on its data type. The data type, the pointer points to,
determines the amount of increment. In this case, yptr is an integer pointer. Therefore,
when we increment the yptr, it points to the next integer in the memory. If an integer
occupies four bytes in the memory, then the yptr++; will increment its value by four.
This can be understood from the following example.
// This program will print the memory address of a pointer and its incremented address.
#include<iostream.h>
main()
{
int y[10]; // an array of 10 integers
int *yptr; // an integer pointer
yptr = y; // assigning the start of array address to pointer
Page 162
// printing the memory address
cout << “The memory address of yptr = “ << yptr << endl ;
yptr++; // incrementing the pointer
// printing the incremented memory address
cout << “The memory address after incrementing yptr = ” << yptr << endl;
}
In the above program, the statement cout << yptr will show the memory address the yptr
points to. You will notice the difference between the two printed addresses. By default,
the memory address is printed in hexadecimal by the C output system. Therefore, the
printed address will be in hexadecimal notation. The difference between the two
addresses will be four as integer occupies four bytes and yptr is a pointer to an integer.
“When a pointer is incremented, it actually jumps the number of memory spaces
according to the data type that it points to”
The sample out put of the program is:
The memory address of yptr = 0x22ff50
The memory address after incrementing yptr = 0x22ff54
yptr
which was pointing to the start of the array y, starts pointing to the next integer in
memory after incrementing it. In other words, yptr is pointing to the 2nd element of the
array. On being incremented again, the yptr will be pointing to the next element of the
array i.e. y[2], and so on. We know that & is address operator which can be used to get
the memory address. Therefore, we can also get the address of the first element of the
array in yptr as:
yptr = &y[0] ;
y[0] is a single element and its address can be got with the use of. the address operator
(&). Similarly we can get the address of 2nd or 3rd element as &y[1], &y[2] respectfully.
We can get the address of any array element and assign it to yptr.
Suppose the yptr is pointing to the first element of the array y. What will happen if we
increment it too much? Say, the array size is 10. Can we increment the yptr up to 12
times? And what will happen? Obviously, we can increment it up to 12 times. In this
case, yptr will be pointing to some memory location containing garbage (i.e. there may
be some value but is useless for us). To display the contents where the yptr is pointing we
can use cout with dereference pointer as:
cout << *yptr ;
Page 163
The above statement will display the contents where yptr is pointing. If the yptr is
pointing to the first element of the array, cout << *yptr will display the contents of the
first element of the array (i.e. y[0]). While incrementing the yptr as yptr ++, the
statement cout << * yptr will display the contents of the 2nd element of the array(i.e.
y[1]) and so on.
Here is an example describing different methods to access array elements.
/* This program contains different ways to access array elements */
#include <iostream.h>
main ()
{
int y[10] = {0,5,10,15,20,25,30,35,40,45};
int *yptr;
yptr = y; // Assigning the address of first element of array.
cout << “Accessing 6th element of array as y[5] = ” << y[5] << endl;
cout << “Accessing 6th element of array as *(yptr + 5) = ” << *(yptr + 5) << endl;
cout << “Accessing 6th element of array as yptr[5] = “ << yptr[5] << endl;
}
The output of the program is:
Accessing 6th element of array as y[5] = 25
Accessing 6th element of array as *(yptr + 5) = 25
Accessing 6th element of array as yptr[5] = 25
In the above example, there are two new expressions i.e. *(yptr+5) and yptr[5]. In the
statement *(yptr+5), yptr is incremented first by 5 (parenthesis are must here).
Resultantly, it points to the 6th element of the array. The dereference pointer gives the
value at that address. As yptr is a pointer to an integer, so it can be used as array name.
So the expression yptr[5] gives us the 6th element of the array.
The following example can explain how we can step through an entire array using
pointer.
/* This program steps through an array using pointer */
#include <iostream.h>
Page 164
main ()
{
int y[10] = {10,20,30,40,50,60,70,80,90,100};
int *yptr, i;
yptr = y; // Assigning the address of first element of array.
for (i = 0; i < 10 ; i ++)
{
cout << “\n The value of the element at position ” << i << “ is “ << *yptr;
yptr ++ ;
}
}
The output of the program is:
The value of the element at position 0 is 10
The value of the element at position 1 is 20
The value of the element at position 2 is 30
The value of the element at position 3 is 40
The value of the element at position 4 is 50
The value of the element at position 5 is 60
The value of the element at position 6 is 70
The value of the element at position 7 is 80
The value of the element at position 8 is 90
The value of the element at position 9 is 100
Consider another example to elaborate the pointer arithmetic.
/* Program using pointer arithmetic */
#include <iostream.h>
main()
{
int x =10;
int *yptr;
yptr = &x;
cout << “The address yptr points to = ” << yptr << endl ;
cout << “The contents yptr points to = ” << *yptr << endl;
Page 165
(*yptr) ++;
cout << “After increment, the contents are ” << *yptr << endl;
cout << “The value of x is = ” << x << endl;
}
The output of the program is:
The address yptr points to = 0x22ff7c
The contents yptr points to = 10
After increment, the contents are 11
The value of x is = 11
Here the statement (*yptr) ++ is read as “increment whatever yptr points to”. This will
increment the value of the variable. As yptr and x both are pointing to the same location,
the contents at that location becomes 11. Consider the statement *yptr + 3 ; This is an
expression and there is no assignment so the value of x will not be changed where as the
statement *yptr += 3; will increment the value of x by 3. If we want to increment the
pointer and not the contents where it points to, we can do this as yptr ++; Now where
yptr
is pointing? The yptr will be now pointing four bytes away from the memory
location of x. The memory location of x is a part of program, yet after incrementing yptr,
it is pointing to some memory area, which is not part of the program. Take this as an
exercise. Print the value of yptr and *yptr and see what is displayed? Be sure, it is not
illegal and the compiler does not complain. The error will be displayed if we try to write
some value at that memory address.
“When a pointer is used to hold the memory address of a simple variable, do not
increment or decrement the pointer. When a pointer is used to hold the address of
an array, it makes sense to increment or decrement the pointer “
Be careful while using pointers, as no warning will be given, in case of any problem. As
pointers can point at any memory location, so one can easily get the computers crashed
by using pointers.
Remember that incrementing the pointer and incrementing the value where the pointer
points to are two different things. When we want to increment the pointer, to make it
point to next element in the memory, we write as (yptr++); Use parenthesis when
incrementing the address. If we want to increment the value where the pointer points to, it
can be written as (*yptr) ++; Keep in mind the precedence of operator. Write a program
to test this.
The decrement of the pointer is also the same. yptr --; yptr -= 3 ; will decrement the yptr.
Whereas the statement (*yptr) --; will decrement the value where the yptr is pointing. So
if the yptr is pointing to x the value of x will be decremented by 1.
Page 166
Pointers are associated to some data type as pointer to integer, pointer to float and pointer
to char etc. When a pointer is incremented or decremented, it changes the address by the
number of bytes occupied by the data type that the pointer points to. For example, if we
have a pointer to an integer, by incrementing the pointer the address will be incremented
by four bytes, provided the integer occupies four bytes on that machine. If it is a pointer
to float and float occupies eight bytes, then by incrementing this pointer, its address will
be incremented by eight bytes. Similarly, in case of a pointer to a char, which normally
takes one byte, incrementing a pointer to char will change the address by one. If we move
to some other architecture like Macintosh, write a simple program to check how many
bytes integer, float or char is taking with the use of simple pointer arithmetic. In the
modern operating systems like windows XP, windows 2000, calculator is provided under
tools menu. Under the view option, select scientific view. Here we can do hexadecimal
calculations. So we can key in the addresses our programs are displaying on the screen
and by subtracting, we can see the difference between the two addresses. Try to write
different programs and experiment with these.
We have seen that we can do different arithmetic operations with pointers. Let's see can
two pointers be added? Suppose we have two pointers yptr1 and yptr2 to integer and
written as yptr1 + yptr2 ; The compiler will show an error in this statement. Think
logically what we can obtain by adding the two memory addresses. Therefore, normally
compiler will not allow this operation. Can we subtract the pointers? Yes, we can.
Suppose we have two pointers pointing to the same memory address. When we subtract
these, the answer will be zero. Similarly, if a pointer is pointing to the first element of an
integer array while another pointer pointing to the second element of the array. We can
subtract the first pointer from second one. Here the answer will be one, i.e. how many
array elements are these two pointers apart.
Consider the following sample program:
/* Program using the pointer subtraction */
#include <iostream.h>
main ()
{
int y[10], *yptr1, *yptr2;
yptr1 = &y[0];
yptr2 = &y[3];
cout << “ The difference = “ << yptr2 - yptr1;
}
The output of the program is:
Page 167
The difference = 3
In the above program, we have taken two integer pointers yptr1 and yptr2 and an integer
array y[10]. The pointer yptr1 is pointing to the address of the first element of the array
while yptr2 is pointing to the 4th element of the array. The difference between these two
pointers can be shown by using cout statement. Here the result should be twelve. But the
program will show the result as three. When we increment an integer pointer by 1, we
have seen that the address is changed by four. When we subtract pointers, it tells us the
distance between the two elements that the pointers pointed to. It will tell us how many
array elements are between these two pointers. As the yptr1 is pointing to y[0] and the
yptr2
is pointing to y[3], so the answer is three. In a way, it tells how many units of data
type (pointers data type) are between the two pointers. Pointer addition is not allowed,
however, pointer subtraction is allowed as it gives the distance between the two pointers
in units, which are the same as the data type of the pointer.
A memory image of an array with a pointer.
This diagram shows how an array occupies space in the memory. Suppose, we have an
integer array named y and yptr is a pointer to an integer and is assigned the address of the
first element of the array. As this is an integer array, so the difference between each
element of the array is of four bytes. When the yptr is incremented, it starts pointing to
the next element in the array.
Pointer Comparison

We have seen pointers in different expressions and arithmetic operations. Can we
compare pointers? Yes, two pointers can be compared. Pointers can be used in
conditional statements as usual variables. All the comparison operators can be used with
pointers i.e. less than, greater than, equal to, etc. Suppose in sorting an array we are using

yptr
y[0] y[1] y[2] y[3] y[4]


Addresses: 3000 3004 3008 3012 3016
yptr++ yptr


Page 168
two pointers. To test which pointer is at higher address, we can compare them and take
decision depending on the result.
Again consider the two pointers to integer i.e. yptr1 and yptr2. Can we compare *yptr1
and *yptr2? Obviously *yptr1 and *yptr2 are simple values. It is the value of integer
yptr1
, yptr2 points to. When we say *yptr1 > *yptr2, this is a comparison of simple two
integer values. Whenever we are using the dereference pointer (pointers with *), all
normal arithmetic and manipulation is valid. Whenever we are using pointers themselves,
then certain type of operations are allowed and restrictions on other. Make a list what can
we do with a pointer and what we cannot.
Consider a sample program as follows:
/* Program using the dereference pointer comparison */
#include <iostream.h>
main ()
{
int x, y, *xptr, *yptr;
cout << “ \n Please enter the value of x = “ ;
cin >> x ;
cout << “ \n Please enter the value of y = “;
cin >> y ;
xptr = &x;
yptr = &y;
if (*xptr > *yptr )
{
cout << “ \n x is greater than y “;
}
else
{
cout << “\n y is greater than x “;
}
}
The output of the program is;
Please enter the value of x = 6
Please enter the value of y = 9
Page 169
y is greater than x
Pointer, String and Arrays

We have four basic data types i.e. char, int, float and double. Character strings are arrays
of characters. Suppose, there is a word or name like Amir to store in one entity. We
cannot store it into a char variable because it can store only one character. For this
purpose, a character array is used. We can write it as:
char name [20];
We have declared an array name of 20 characters .It can be initialized as:
name[0] = ‘A’ ;
name[1] = ‘m’ ;
name[2] = ‘i’ ;
name[3] = ‘r’ ;
Each array element is initialized with a single character enclosed in single quote. We
cannot use more than one character in single quotes, as it is a syntax error. Is the
initialization of the array complete? No, the character strings are always terminated by
null character ‘\0’. Therefore, we have to put the null character in the end of the array.
name[4] = ‘\0’ ;
Here we are using two characters in single quotes. But it is a special case. Whenever back
slash ( \ ) is used, the compiler considers both the characters as single (also known as
escape characters). So ‘\n’ is new line character, ‘\t’ a tab character and ‘\0’ a null
character. All of these are considered as single characters. What is the benefit of having
this null character at the end of the string? Write a program, do not use the null character
in the string and try to print the character array using cout and see what happens? cout
uses the null character as the string terminating point. So if cout does not find the null
character it will keep on printing. Remember, if we want to store fifteen characters in an
array, the array size should be at least sixteen i.e. fifteen for the data and one for the null
character. Do we always need to write the null character at the end of the char array by
ourselves? Not always, there is a short hand provided in C, i.e. while declaring we can
initialize the arrays as:
char name[20] = “Amir”;
When we use double quotes to initialize the character array, the compiler appends null
character at the end of the string.
Page 170
“Arrays must be at least one character space larger than the number of printable
characters which are to be stored”

Example:


Write a program which copies a character array into given array.

Solution:


Here is the complete code of the program:
/* This program copies a character array into a given array */
#include <iostream.h>
main( )
{
char strA[80] = "A test string";
char strB[80];
char *ptrA; /* a pointer to type character */
char *ptrB; /* another pointer to type character */
ptrA = strA; /* point ptrA at string A */
ptrB = strB; /* point ptrB at string B */
while(*ptrA != '\0')
{
*ptrB++ = *ptrA++; // copying character by character
}
*ptrB = '\0';
cout << “String in strA = ” << strA << endl; /* show strA on screen */
cout << “String in strB = ” << strB << endl; /* show strB on screen */
}
The output of the program is:
String in strA = A test string
String in strB = A test string
Page 171

Explanation:


Suppose, we have declared a char array named strA of size 80 and initialized it with some
value say “A test String” using the double quotes. Here we don’t need to put a null
character. The compiler will automatically insert it. But while declaring another array
strB
of the same size, we declare two char pointers *ptrA and *ptrB. The objective of this
exercise is to copy one array into another array. We have assigned the starting address of
array strA to ptrA and strB to ptrB. Now we have to run a loop to copy all the characters
from one array to other. To terminate the loop, we have to know about the actual number
of characters or have to use the string termination character. As we know, null character
is used to terminate a string, so we are using the condition in 'while loop' as: *ptrA != ‘\0’
, simply checking that whatever ptrA is pointing to is not equal to ‘\0’. Look at the
statement *ptrB++ = *ptrA++. What has happened in this statement? First of all,
whatever ptrA is pointing to will be assigned to the location where ptrB is pointing to.
When the loop starts, these pointers are pointing to the start of the array. So the first
character of strA will be copied to the first character of strB. Afterwards, the pointers will
be incremented, not the values they are pointing to. Therefore, ptrA is pointing to the 2nd
element of the array strA and ptrB is pointing to the 2nd element of the array strB. In the
2nd repetition, the loop condition will be tested. If ptrA is not pointing to a null character
the assignment for the 2nd element of the array takes place and so on till the null character
is reached. So all the characters of array strA are copied to array strB. Is this program
complete? No, the array strB is not containing the null character at the end of the string.
Therefore, we have explicitly assigned the null character to strB. Do we need to
increment the array pointer? No, simply due to the fact that in the assignment statement (
*ptrA++ = *ptrB++;), the pointers are incremented after the assignment. This program
now successfully copies one string to other using only pointers. We can also write a
function for the string copy. The prototype of the function will be as:
void myStringCopy (char *destination, const char *source) ;
This function takes two arguments. The first one is a pointer to a char while second
argument is a const pointer to char. The destination array will be changed and all the
characters from source array are copied to destination. At the same time, we do not want
that the contents of source should be changed. So we used the keyword const with it. The
keyword const makes it read only and it can not be changed accidentally. If we try to
change the contents of source array, the compiler will give an error. The body is same, as
we have seen in the above program.
This function will not return anything as we are using pointers. It is automatically call by
reference. Whenever arrays are passed to functions, a reference of the original array is
passed. Therefore, any change in the array elements in the function will change the actual
array. The values will be written to the original array. If these are simple variables, we
will have to send the address and get the called program to change it. Therefore, we do
not need to return anything from this function after successfully copying an array into the
other.
Here is the code of the function. Write a program to test this function.
Page 172
void myStringCopy (char *destination, const char *source)
{
while(*source != ‘\0’)
{
*destination++ = *source++;
}
*destination = ‘\0’;
}
We can also write the string copy function using arrays. Here is the code of the
myStringCopy function using arrays notation.
void myStringCopy(char dest[], char source[])
{
int i = 0;
while (source[i] != '\0')
{
dest[i] = source[i];
i++;
}
dest[i] = '\0';
}

Exercise:


1) Print out the address and the value of a character pointer pointing to some
character.
2) Write a function which copies an array of integers from one array to other

Tips


While incrementing the pointers, use the parenthesis
Increment and decrement the pointers while using arrays
When a pointer is incremented or decremented, it changes the address by the
number of bytes occupied by the data type that the pointer points to
Use key word const with pointers to avoid unwanted changes
The name of array is a constant pointer. It cannot be reassigned

<Previous Lesson

Introduction to Programming

Next Lesson>

Home

Lesson Plan

Topics

Go to Top

Copyright © 2008-2013 zainbooks All Rights Reserved
Next Lesson
Previous Lesson
Lesson Plan
Topics
Home
Go to Top