Pointers in c++

AsayeDilbo 874 views 20 slides May 12, 2017
Slide 1
Slide 1 of 20
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20

About This Presentation

An interesting note about pointers in C++.


Slide Content

By: Asaye Chemeda Email: [email protected] 26

CHAPTER THREE 
POINTERS 
 
Introduction 
The data types in C++ are broadly categorized into simple 
data types, structured data types and pointers. We have 
already  seen  the  first  two.  In  this  chapter,  we  will  deal 
about  the  third  categories  of  data  types  in  C++,  i.e., 
pointers. Their name is coined from the fact that these 
data  types  point  to  another  data.  Pointer  variables,  or 
shortly pointers, are data types which are derived based 
on other data types. There is also no name associated with 
the data type of pointers. However, they are considered 
to be a separate data types in C++. 
Pointer variables are used to store memory addresses of 
the  variables  they  point  to.  The  variables  which  are 
pointed to by pointers have a name for their data types, 
unless they are pointers themselves. Even if the data type 
of  pointers  has  no  name  in  C++,  pointers  are  usually 
considered to have the same data type as the variable they 
point to and are defined as such.  However, there are also 
pointers called generic pointers with void data type. 
These types of pointers can point to any variable with any 
data type. They can also be assigned with other pointers 
which point to any data type. 
Since  pointers  refer  to  the  memory  addresses  of  other 
variables, they are very powerful means for manipulation 
of  data  in  C++.  Pointers  will  provide  you  the  way  by 
which you can manipulate data which other conventional 
approaches fail to do. Thus, they are very useful tools in 
C++.  However,  they  may  also  have  undesirable 
consequences  unless  they  are  handled  carefully  in  a 
program. 
Defining Pointers 
Pointers  take  the  same  data  type  but  different  content 
than the variables which they point to. If so, how are these 
pointer  variables  are  defined?  What  makes  them  be 
distinguished from non-pointer variables? 
Pointer  variables  are  distinguished  from  other  non-
pointer variables by using the asterisk symbol, ‘*’, during 
their definition. If the asterisk symbol is put in front of a 
variable during its declaration, the compiler will consider 
it  to  be  a  pointer.  The  asterisk  symbol  can  appear 
anywhere between the data type and the pointer variable. 
However, it is a good practice to pre-attach it with the 
pointer  variable.  The  syntax  used  to  define  a  pointer 
variable is: 
 
In the above declaration, the dataType , which can also 
be void,  is  usually  the  same  as  the  data  type  of  the 
variable that the pointerVariable points to. 
Once a pointer variable is defined, how it is then used for 
data  manipulation?  Before  answering  this  question, we 
will  discuss  about  two  operators  which  are  often  used 
with pointers. They are the address of operator denoted 
by the ampersand symbol, ‘&’ and the dereferencing or 
at  address or  indirection  operator  denoted  by  the 
asterisk symbol,’*’. The address of operator returns the 
memory address of its operand while the dereferencing 
operator  returns  the  value  stored  at  a  given  memory 
location.  To  understand  this  a  bit  more,  let  us  see  the 
following piece of code. 
 
In the above code, an integer variable x is defined and 
initialized with a value of 100 on line 1. As you know, 
when values are declared, a memory space is allocated for 
the  variables  during  compile  time.  Those  memory 
locations  have  addresses.  Let  us  say  that  the  memory 
address where x is stored, amongst others, is 1000. Let us 
depict this diagrammatically as follows. 
 
The above diagram shows that at memory location 1000, 
an integer value of 100 is stored. 
On line 2, a pointer variable p is declared by using the * 
symbol.  Which  means  that  the  variable p  will  store 
memory address of another variable, i.e., p is declared to 
point  to  another  variable.  The int  data  type  that  the 
pointer variable is declared by indicates that the pointer 
will point to a variable with int data type. Again, a separate 
memory location will be allocated for this variable. Let us 
say the memory location allocated for p has an address of 
1003. When we depict this graphically, as in the above 
diagram, we will have the following. 
 
The above diagram shows that a memory address of 1003 
is allocated for the additional variable p. Note that, the 
pointer variable is not yet initialized and at this stage it can 
point to any memory location. If your program tries to 

By: Asaye Chemeda Email: [email protected] 27

access memory address 1003 which is not yet initialized 
and use the address which it points to now, your program 
may  be  directed  to  any  memory  location  even  those 
having sensitive system data and your computer system 
may  crash.  Line  3  shows  how  a  pointer  variable  is 
initialized. 
On line 3, p is assigned with the address of variable x by 
using the address of operator &. The part on the right 
hand side of the assignment operator ( = ), ‘&x’, returns 
the  memory  address  of  variable x.  The  assignment 
operator will assign this address to the pointer variable p 
on  the  left  hand  side.  Which  means  that  the  memory 
address of variable x, which is 1000, will be stored in the 
memory address of p, which is 1003. In short, p is now 
pointing to variable x. After this, the memory locations 
will appear to be: 
 
In  the  above  diagram,  the  memory  address  1003  now 
contains  another  memory  address  1000,  which  is  the 
memory address of variable x. After the initialization on 
line 3, the variable p points to a specific known address 
and you can use it without any harm to your computer. 
On line 4, the value at address contained by variable p is 
assigned  with  value  of  25  by  using  the  dereferencing 
operator *. The part on the left hand size of assignment 
operator of the statement, *p, refers to the value stored 
at memory address contained by pointer variable p.  The 
memory address contained by p is 1000 and the value at 
address 1000 was 100. Therefore, the statement on line 4 
changes this value to 25. Diagrammatically, what happens 
after line 4 is shown as follows: 
 
In the above diagram, the value at address 1000 is now 
changed  to  25.  Note  that,  memory  address  1003  still 
contains the memory location of variable x and further 
changes  can  be  made  through  the  same  procedure. 
However, the pointer variable p can also be made to point 
to another variable. 
The  way  how  pointers  manipulate  data  in  C++  is  as 
simple  as  what  we  discussed  above.  But  that  is  not all 
about  pointers.  Based  on  the  above  concept,  we  can 
utilize pointers to access and manipulate data in different 
ways. Before proceeding to those details, don’t you think 
it is good if we can incorporate the above piece of code 
into a full program and see the results? If that is also your 
thought, let us see the following program.  
Program 3.1[Correct].cpp 
 
When the above program is run, the resulting output is 
shown below. Note that, the address results are machine 
dependent and you may obtain different addresses than 
those shown below. 
 
What we confirmed from the above output is that 
(1) The 
address  of x  can  be  obtained  by  either  the  address  of 
operator & or by the pointer variable p which points to 
the variable x (Line 9 of the program and line 1 of the output). 
(2) A memory location is also allocated for the pointer 
variable p which can be obtained by the & operator (Line 
11 of the program and line 2 of the output). 
(3) The value of the 
variable x can be obtained from the variable itself or from 
its pointer variable p by using the dereferencing operator 
*. (Line 13 of the program and line 3 of the output). 
(4) The 
value of the variable x can be changed by using the * 
operator and its pointer variable p. (Line 15 of the program 
and line 4 of the output). 
Have you noticed that pointers are variables themselves? 
Their difference from other non-pointer variables are due 
to the type of data they store being different from other 
simple  or  structured  data  types.  You  may  ask  the 
following string of questions. If pointers are variables, can 
we  perform  arithmetic  operations  on  them?  If  it  is 
possible, what do the results of arithmetic operations on 
pointers  refer  to?  Do  the  results  even  have  any  real 
purpose  in  programming?  All  these  questions  will  be 
answered in the following topic. 
Pointer Arithmetic 
Besides  being  assigned  with  and  compared  to  another 
pointer variable, only the following arithmetic operations 
can be performed on pointers. 
1. Pointer  variables  can  be  incremented  or 
decremented. 

By: Asaye Chemeda Email: [email protected] 28

2. Integer values can be added or subtracted from 
pointers. 
3. One  pointer  variable  can  be  deducted  from 
another pointer variable. 
Note that any other arithmetic operation is prohibited on 
pointers. Understanding the above arithmetic operations 
to a modest detail is helpful and they will be discussed 
below. 
Assigning pointer with another pointer or a value. A 
pointer is not only assigned or initialized with the help of 
the &  operator.  A  pointer  can  also  be  assigned  or 
initialized  with  another  pointer.  After  the  assignment, 
both the assigned and the assigning pointers refer to the 
same memory location. Let us have a look at the following 
piece of code. 
 
On line 1, a character variable c is declared and initialized 
with a character literal ‘A’. On line 2, pointers p1 and p2 
are declared. On line 3, p1 is initialized with the address 
of c. On line 4, p2 is assigned with p1. After line 4, both 
p1 and p2 will point to c. What each line of the above 
piece  of  code  will  do  is  graphically  depicted  as  below. 
Note that the memory addresses are arbitrary. 
 
Pointers of any data type can also be assigned with only 
one value, i.e. ‘0’. Pointers which are assigned with this 
value are called null pointers and they point to nothing. 
Null pointers can also be created by assigning pointers of 
any  data  type  with  the  word  ‘NULL’.  Null  pointers  are 
conventionally  used  to  avoid  problems  caused  by 
uninitialized pointers. 
Comparison of pointer variables. A comparison can be 
made between two pointers. In general, pointers can be 
used  in  logical  comparison  statements.  These 
comparisons,  however,  are  based  on  the  equality  or 
otherwise  of  the  addresses  contained  by  pointers.  For 
instance, if p and q are two pointers, 
• p == q returns true if the memory address in p 
is equal to that in q or false otherwise. 
• p < q returns true if the memory address in p is 
less than that in q or false otherwise. 
• p > q returns true if the memory address in p is 
greater than that in q or false otherwise. 
Such  pointer  comparisons  might  be  useful  if  we  are 
interested to know whether two pointers refer to the same 
memory address or not. However, the purpose of pointer 
comparison  is  not  limited  to  this  and  you  can  use  the 
concept whenever appropriate. 
Incrementing or decrementing of pointers. The values 
of  pointers  can  be  incremented  by  the ++ operator  or 
decremented by the --  operator. What the incrementing 
or decrementing operations will do the pointer variable is 
interesting.  When  a  pointer  is  incremented  or 
decremented, the value by which the pointer will do as 
such  depends  on  the  data  type  of  the  pointer.  For 
character pointers which point to characters which always 
have  1byte  size,  an  increment  adds  one  to  the  pointer 
where as a decrement subtracts one from the pointer. For 
integer  pointers  which  point  to int  variables  which 
normally have 4byte size, an increment adds four to the 
pointer  where  as  a  decrement  subtracts  four  from  the 
pointer. In short, the increment or decrement of pointers 
is done by an amount equal to the memory size allocated 
for a single base data type. 
Usually,  memory  addresses  correspond  to  hexadecimal 
numbers. However, for simplicity purposes, we will use 
memory addresses with integer values and we will see how 
incrementing  and  decrementing  is  done  for  pointers 
which point to different data types. Since the procedure is 
similar for different data types, we will only deal with char 
and int data types. 
Increment and decrement in 
char pointers 
Let us refer to the following piece of code. 
 
On line 1 of the above of code, character variables c1, 
c2  and c3  are  declared  and  initialized  with  character 
literals ‘A’, ‘B’ and ‘C’ respectively. On line 2, a pointer 
pChar with char data type is declared and initialized with 
address of c1. At this point, pChar points to c1. Let us 
assume  that c1, c2  and c3  are  stored  in  contiguous 

By: Asaye Chemeda Email: [email protected] 29

memory locations with addresses of 2000, 2001 and 2002 
respectively  and pChar  is  stored  at  memory  address 
2004. At this point, pChar and *pChar are equal to
2000 and ‘A’ respectively. This is depicted in a diagram 
as follows. 
 
When pChar  is  incremented  on  line  3,  the  memory 
address in pChar will be incremented by the amount of 
the memory size of a single character variable, which is 1. 
After  the  increment,  the  memory  address  in pChar 
becomes 2001. Which means that pChar now points to 
c2. Thus, pChar and *pChar are equal to 2001
and ‘B’ respectively. Diagrammatically, this is represented 
as: 
 
When pChar is incremented on line 4 one more time, 
the memory address in pChar will be incremented by 1. 
After  the  increment,  the  memory  address  in pChar 
becomes 2002. Which means that pChar now points to 
c3. Thus, pChar and *pChar are equal to 2002
and ‘C’ respectively. When this is put in diagram, we will 
have: 
 
When pChar  is  decremented  on  line  5,  the  memory 
address in pChar will be decremented by 1 and becomes 
2001.  Which  means  that pChar  now  points  to c2
again. Thus, pChar and *pChar are equal to 2001
and ‘B’ respectively. When this is put in diagram, we will 
have: 
 
Increment and decrement in 
int pointers 
Let us refer to the following piece of code. 
 
On line 1 of the above of code, int variables i1, i2 and 
i3 are declared and initialized with integer values ‘75’, 
‘83’ and ‘49’ respectively. On line 2, a pointer pInt with 
int data type is declared and initialized with address of i1. 
At this point, pInt points to i1. Since the memory size 
of int data types is normally 4bytes, each integer variable 
requires four memory cells. Let us assume that i1, i2 
and i3 are stored in contiguous memory locations with 
the first cell addresses of 10, 14 and 18 respectively and 
pInt  is  stored  at  memory  address  26.  At  this  point, 
pInt and *pInt are equal to 10 and 75 respectively. 
This  is  depicted  in  a  diagram  as  follows.  The  memory 
addresses  are  written  for  alternate  cells  to  avoid 
congestion of characters. 
 
When pInt  is  incremented  on  line  3,  the  memory 
address in pInt will be incremented by the amount of 
the memory size of a single int variable, which is 4. After 
the increment, the memory address in pInt becomes 14 
not 11. Which means that pInt now points to the next 
int variable which is i2. Thus, pInt and *pInt
are equal to 14 and 83 respectively. Diagrammatically, 
this is represented as: 
 
When pInt is incremented on line 4 one more time, the 
memory address in pInt will be incremented by 4. After 
the increment, the memory address in pInt becomes 18. 
Which  means  that pInt  now  points  to i3. Thus,
pInt and *pInt are  equal  to 18 and 49 
respectively. When this is put in diagram, we will have: 
 
When pInt  is  decremented  on  line  5,  the  memory 
address in pInt will be decremented by 4 and becomes 
14. Which means that pInt now points to i2 again.
Thus, pInt and *pInt are equal to 14 and 83 
respectively. When this is put in diagram, we will have: 
 
Isn’t the way that the compiler handles incrementing and 
decrementing operations on pointers fascinating? Indeed 

By: Asaye Chemeda Email: [email protected] 30

it is. But, have you noted this? In the above examples we 
assumed  that  the  variables  are  stored  in  contiguous 
(interconnected) memory locations. But, is that always the 
case? Not necessarily. Simple data type values may not be 
stored as such. As a result, it may be difficult to keep track 
of the memory locations for variables belonging to simple 
data  types  and  trying  to  use  the  incrementing  and 
decrementing  operators  to  access  values  of  such  data 
types  may  result  in  wrong  calculation  results  or  data 
corruption. If so, what is the importance of incrementing 
and decrementing pointers? 
Here  is  the  answer  for  the  above  question.  Some  data 
types  are  stored  in  the  main  memory  in  a  structured 
manner.  Structured  data  types  such  as  arrays  are  good 
example for this. When elements of arrays are stored in 
the main memory, the compiler will allocate contiguous 
memory locations for them. Therefore, if the address of 
the  first  element  is  known,  the  address  of  the  other 
elements can easily be tracked based on the memory size 
requirement for each element. 
As you may recall, the identifier used for defining arrays 
refers to the address of the first element. In other words, 
the identifier of an array is a pointer to the first array element. The 
identifier can be assigned to a pointer. Based on a pointer 
which is assigned with identifier of an array, the memory 
addresses of all the other elements can easily be obtained 
through incrementing and decrementing. You see, that is 
where the incrementing and decrementing operations on 
pointers become very useful.  
In chapter two, we have seen how arrays are passed to 
functions. Do you remember how it was done? It was by 
reference, right? After our recent discussion, do you see 
another way by which arrays can be passed to functions? 
Let me give you a hint. Just remember how the following 
four things are done. How value is transferred from the 
argument  passed  to  the  formal  parameter  list  of  the 
function  when  a  function  is  called.  How  pointers  are 
declared. What the identifier of an array refers to. And 
how pointer increment and decrement is done. 
When we revise how the above four things are done, we 
will get the following. When a function is called by passing 
arguments,  the  called  function  defines  and  assigns the 
variables  in  its  formal  parameter  list  with  the  passed 
arguments according to their order. Pointer variables are 
declared by pre-attaching * to the name of the pointer 
variable. The identifier of an array is a pointer to the first 
element  of  the  array.  Pointer  incrementing  and 
decrementing is normally done to access and manipulate 
data in contiguous memory locations by increment and 
decrement operators. 
Now, let us see how we can take the above knowledge to 
our advantage to pass arrays to functions and manipulate 
the elements of the array. When a function call is made to 
pass an array, let the calling function pass the identifier of 
the array. Let us make the corresponding argument on the 
formal  parameter  list  of  the  called  function  to  be a 
pointer. Which means that, during function call, the array 
identifier,  which  is  a  pointer,  will  be  assigned  to  the 
corresponding  pointer  variable  in  the  called  function. 
Inside  the  body  of  the  called  function,  all  the  array 
elements  can  now  be  accessed  and  manipulated  by 
incrementing  and  decrementing  the  pointer  which  is 
assigned  by  the  array  identifier.  Don’t  you think  it  is  a 
good strategy? Of course it is. This way of passing arrays 
to functions is termed as passing arrays by pointers and 
if the program is well-written, it is the neatest way to pass 
arrays. Note that, the changes made on the pointers of 
array  elements  inside  the  body  of  the  function  is  also 
reflected in the calling environment. The above way of 
passing  arrays  is  applicable  for  one-dimensional  arrays. 
Passing two-dimensional arrays can also be done through 
pointers.  But,  let  us  keep  discussing  this  concept aside 
until we start dealing with the ‘pointers and arrays’ topic. 
I feel that we have discussed lots of concepts and we need 
to take a break. Do you also feel the same? However, in 
the meantime, let us write a program through which we 
will be able to understand what we discussed so far about 
arithmetic operations on pointers as well as about passing 
arrays by pointers. Here is the program. 
Program 3.2 [Correct].cpp 
 

By: Asaye Chemeda Email: [email protected] 31

The above program calculates the cube roots of the first 
five positive perfect cubes by the cubeRoot function 
and prints the cube roots by the print function. We will 
only discuss the important points in the program. 
On  line  11,  the cubeRoot  function  is  called  and  the 
identifier  of  the cube  array  is  passed  as  an  argument. 
Technically, what is passed as an argument is a pointer to 
the  first  element  of  the cube  array.  When  the 
cubeRoot function is invoked by this call, the first thing 
the  function  is  going  to  do  is  assigning  its  formal 
parameter accordingly with the passed argument. In C++ 
statement, this assignment is represented as: 
 
Isn’t this how a pointer is declared initialized with another 
pointer? Of course it is. In the above declaration, we need 
to understand that the data type of c is double and it can 
only be initialized with a pointer of only double data type. 
After the above declaration the pointer c will contain the 
memory address of the first element of the cube array. 
On line 17, the cube root of the value at address contained 
by c  is  calculated  and  stored  in  the  same  address 
contained by c. On line 18, the pointer is incremented. 
After each increment, the pointer c will point to the next 
element in the contiguous memory location, i.e., the next 
element of cube array. The for-loop controls for how 
many times that the increment will be done. When the 
loop is complete, all the elements of the cube array will 
now contain the cube roots of the corresponding original 
values. This change is also reflected in the main function 
where  the cubeRoot  function  is  called.  Therefore, 
when the array identifier cube is now passed to the print 
function on line 12, it refers to the memory address of the 
first element of the changed cube array elements not those 
elements given on line 10. 
Note that the data type of the formal parameter of the 
print function is void. This means that, the cubeRt 
pointer  is  a  void  pointer  which  can  be  assigned  with 
another  pointer  which  points  to  a  variable  of  any  data 
type.  However,  to  access  and  manipulate  the  data 
contained by the cubeRt pointer, explicit type casting 
should be made. Type casting is conversion of one data 
type into another. One way to do this in C++ is by putting 
the data type to be converted to within brackets in front 
of the variable which we want to convert its data type as 
it was done on line 22. However, type casting may not be 
applicable for conversion between some data types. Note 
that the casting on line 22 could also be done by using the 
static_cast key word and the data type to be casted 
to within angled brackets as in the following statement: 
 
On line 22 of the program, the void cubeRt pointer is 
casted  or  converted  to double  pointer  and  the  casted 
pointer is assigned to a double pointer named x. Through 
pointer x,  the  elements  of  the  array x  can  now  be 
accessed  and  printed  by  using  the  increment  operator. 
The part of the statement on line 24, *x++, means access 
the value stored at address contained by x and increment 
the pointer x to the next value. 
I hope the above example clears any doubts you might 
have  regarding  pointer  incrementing  and  passing  one-
dimensional arrays to functions as pointers. Remember, 
we  haven’t  yet  covered  all  the  possible  arithmetic 
operations on pointers; two more are remaining. 
Adding  or  subtracting  integers  from  pointer 
variables. If  you  understand  how  incrementing  and 
decrementing  of  pointers  is  done,  understanding  how 
adding or subtracting of integers is done is pretty easy. As 
you know, when incrementing is done by the ++ operator, 
the  value  of  the  variable  on  which  the  incrementing  is 
done will be increased by sizeof(base data type of the 
variable). The keyword sizeof is a reserved C++ word 
used to return the size of the memory space allocated for 
objects. The value sizeof(base data type) of  may not 
merely mean one. It may mean one for char pointers, 
four  for int  pointers  or eight  for double  pointers. 
Adding an integer i to a pointer, therefore, means adding 
i times size of the pointer variable. The same is true for 
subtracting integers. Let us see this through the following 
piece of code. 
 
In the above piece of code, a double variable x is defined 
and initialized on line 1. On line 2, a double pointer p is 
defined  and  initialized  with  the  address  of x.  Say  the 
address of x is 100. After line 2, the value of p will be 100. 
Double  data  types  normally  require  8bytes.  A  single 
increment on pointer p by ++ will result in a value of p 
to be 108. However, on line 3, the value of p is increased 
by 10. What do you think will the value of p become after 
line 3 when the value of p after line 2 is 100? Are you 
saying 110? If you say so, you might have forgotten how 
incrementing of pointers is done.  
When 10 is added to a double data type pointer variable, 
the value of the pointer will be incremented by 10 times 
sizeof(double) (i.e., 8). In other words, when 10 is 
added  to  pointer p,  the  value  of  the  pointer  will  be 
incremented by 80. Therefore after line 3, the value of p 
becomes 180.  
Subtracting integers from pointers is also done in a similar 
procedure. 

By: Asaye Chemeda Email: [email protected] 32

Deducting  two  pointer  variables. Two  pointers 
pointing to the same data type may also be deducted from 
each other. The difference between two pointers results 
in an integer value. The absolute value of the resulting 
integer represents the number of objects of the base data 
type between the pointers. The difference between two 
pointers, however, cannot be assigned to another pointer 
even if the difference is equal to zero.  
We have now seen the only possible arithmetic operations 
on pointers. The following operations, amongst others, 
are prohibited. 
• Adding two pointers 
• Assigning non-zero values to pointers 
• Adding  or  subtracting  floating-point  data  type 
values from pointers. 
• Multiplying or dividing two pointers. 
At this point, we have discussed the basics of pointers and 
pointer  operations.  Let  us  proceed  further  and  discuss 
other  details.  Have  you  ever  imagined  that  there  could 
also  be  array  of  pointers?  Indeed,  there  are  arrays  of 
pointers too. 
The concept of arrays of pointers integrates the concepts 
of both arrays and pointers. Arrays of pointers are arrays 
which contain pointers as elements. They are declared and 
used in the same way as other arrays. The only difference 
is the asterisk symbol should be used to tell the compiler 
that the array is an array of pointers. For instance, an array 
of int pointers x having 10 elements can be declared as 
follows. 
 
What would x store if it was just an int array declared 
without the asterisk? Ten integer values, right? Because of 
the asterisk, however, x is declared as a pointer array and 
it stores ten memory addresses with each memory address 
pointing to an int variable. After this declaration, x can 
be initialized with memory addresses of other variables. If 
we  want  to  initialize  the  fourth  element  of x  with  the 
address of an int variable y, we can write the following: 
 
Now, if we want to initialize the value of y by 76, we can 
use the following statement: 
 
We have discussed that pointers point to other variables 
which have their own data types. The interesting question 
here is: can pointers point to another pointers? Of course, 
they can. Simply, ask yourself what the name of array of 
pointers  represents.  If  you  understand  what  kind  of 
pointer that a name of array of pointers is, reading the 
next topic might not be necessary. Otherwise, go through 
the next topic for a better understanding. 
Multiple Indirection 
Pointers are variables themselves and a memory location 
is  allocated  for  them.  If  a  pointer  stores  the  memory 
location allocated for another pointer variable, the pointer 
is  pointing  to  another  pointer  variable.  In  C++,  the 
process  of  pointing  at  another  pointer  is  known  as 
multiple  indirection.  The  pointer  with  multiple 
indirection is known as pointer to a pointer. The process 
of  multiple  indirection  can  be  repeated  as  many  as we 
want  although  more  than  three  multiple  indirection is 
rarely used in programming. 
Pointers to pointers can be defined in the same way as 
other  pointers  with  only  one  indirection.  The  only 
difference is, as many asterisk symbols as the number of 
indirections will be put between the pointer and data type 
of the pointer. The data type of pointers with multiple 
indirection will be the same as the data type of the target 
value. 
A  pointer  with  two  indirections  is  declared  with  the 
following syntax. 
 
In  the  above  declaration,  the  two  asterisk  symbols 
between  the pointerVariable  and dataType 
indicate  that  the pointerVariable  will  point  to 
another pointer. 
Pointers to pointers can only be assigned with address of 
other pointers or ‘0’. The way how we use the address of 
operator (&) and the indirection operator (*) while using 
pointers to pointers is the same as simple pointers. The 
target  value  can  also  be  accessed  and  manipulated  by 
pointers to pointer by using as many indirection operators 
as they are used to define the pointer to pointer. 
It is easy, right? If not, the following simple program will 
make it so. 
Program 3.3[Correct].cpp 
 

By: Asaye Chemeda Email: [email protected] 33

In the above program, a float variable x is defined and 
initialized on line 6. A pointer p and a pointer to pointer 
pTp are defined on line 7. Note that, if p is supposed to 
point to x and if pTp is supposed to point to p, the data 
type of pTp will also be the same as the data type of x. 
that is the reason why p and pTp were defined as such. 
On line 8, the address of variable x is assigned to p and 
on line 9, the address of p is assigned to pTp. Note that, 
trying  to  assign pTp  with  address  of  a  non-pointer 
variable such as x rather than with address of a pointer 
would have resulted in compilation error. 
From the above program, the main expected outcome is 
that the output of line 10 and line 13 to be the same. If 
you understand why this should be, it means that you have 
understood multiple indirection. If not, there should be 
no worries as we will go through the output of the five 
cout statements.  
The output of the statement on line 10 is the address of 
the variable x contained in p. Since p is assigned with the 
address of p on line 8, displaying the value of p by cout 
statement will result in displaying the memory address of 
x. 
The  value  of pTp  will  be  displayed  by  the cout 
statement  on  line  11.  The  output  of  this  line  is  the 
memory address of p contained in pTp. This is because 
pTp is assigned with the address of p on line 9. 
Through  the  indirection  operator,  the  value  at  address 
contained in p will be displayed as an output of line 12. 
What  is  address  contained  in p?  It  is  the  address  of 
variable x, right? Therefore, *p access the value of x. 
When  we  come  to  the  statement  on  line  13,  a  value 
referred by *pTp will be printed. This means the value at 
address contained by pTp will be displayed. On line 9, 
pTp is assigned with the address of p. Therefore, pTp 
contains the address of p and *pTp accesses the value at 
the  address  contained  by pTp  which  is  the  value  of p 
which is also the address of x. Therefore, *pTp and p 
refer to the same thing and the output of line 10 and line 
13 will be the same. 
The  value  of x  can  also  be  accessed  through pTp  by 
applying the same number of indirection operators as it 
was used to define pTp. The cout statement on line 14, 
which prints the value of **pTp, actually prints the value 
of x. We have seen above that when the * is pre-attached 
once  on pTp,  it  accesses p,  when  another  one  is  pre-
attached, the value of x will be accessed. 
Although the memory addresses are machine dependent, 
the output of the above program is shown below. As can 
be observed, the memory addresses printed on the first 
and forth lines of the output are the same which asserts 
our explanation above. 
 
I  guess  you  have  mixed  feelings  about  multiple 
indirections. On one hand, you may wonder how pointers 
to pointers work to access and manipulate values. One the 
other hand, you may be curious about what the purpose 
of defining pointers to pointers is. Am I right? If so, my 
suggestion is to keep on your wondering about multiple 
indirections.  And  the  following  topic  will  answer  your 
curiosity. 
Pointers and Arrays 
In C++, pointers and arrays are interrelated. The second 
chapter on arrays and our discussion so far in this chapter 
about  pointers  have  provided  us  the  subtle  differences 
between them. In C++ programming, pointers are often 
used to access and manipulate array elements. Arrays can 
also be used as pointers. In our discussion about arrays in 
chapter two, we have said that array names refer to the 
memory locations of the first array elements. Therefore, 
array names are pointers themselves. Even if array names 
are  pointers,  you  can’t  perform  pointer  arithmetic on 
them which attempts to change their values. In general, 
array names are constant pointers. 
You  may  ask,  in  what  way  are  arrays  and  pointers  are 
interrelated? We have already seen how one-dimensional 
arrays  and  pointers  can  be  interrelated  during  our 
discussion on  incrementing  and  decrementing  pointers. 
The  concepts  which  were  not  discussed  then,  will  be 
covered in this topic. 
Let  us  start  discussing  more  about  the  relationship 
between arrays and pointers for one dimensional arrays. 
Consider  the  following  one-dimensional  array 
declaration: 
 
In the above array the name numbers is a pointer to the 
first array element, i.e. it contains the memory address of 
the  value 10.  Through  indexing,  the  first  element  is 
accessed  by numbers[0].  Therefore,  the  following 
logical statement returns true. 
 

By: Asaye Chemeda Email: [email protected] 34

The  above  logical  statement  compares  the  equality 
between numbers and the address of numbers[0]. 
Since  the  returned  value  is true,  it  means  that 
numbers contains the address of numbers[0]. Thus, 
numbers is a pointer. If numbers is dereferenced, it 
gives the value of the first array element. The following 
logical statement will, therefore, return true. 
 
The first array element can also be changed to another int 
value,  say 15,  by  using  the  array  name  through  the 
following statement. 
 
So far so good. The array name, numbers, is behaving 
exactly  the  same  as  other  regular  pointers.  Can  we 
conclude that array name can be used as like any other 
pointer?  Before rushing  to the  conclusion,  let  us  apply 
some arithmetic operations on numbers and let us see 
how it behaves. 
First,  let  us  apply  the  incrementing  operation  on 
numbers and let us point to the next element of the 
array. Recall that incrementing pointers will make them 
point  to  the  next  element  in  contiguous  memory 
locations.  Trying  to  point  to  the  next  element  of  the 
numbers  array  through  the  following  statement, 
however, results in compilation error. 
 
Array names are not like other pointers, after all. Can you 
guess what the reason for the compilation error could be? 
It is the ++ operator. Since the data type of the array is 
int, the above statement attempted to increment the value 
of numbers by sizeof(int). But, array names are 
constant pointers and their values cannot be changed and 
they only point to the first array element. This rule is not 
limited  for  only  incrementing,  any  other  arithmetic 
operation which attempts to change the value of an array 
name is illegal. We can now conclude that array names are 
pointers with restrictions. 
 If  incrementing  and  decrementing  is  illegal  on  array 
names,  we  may  think  that, they  are  useless  to  point  to 
other array elements than the first one. However, that is 
not true at all. Array names can also be used to point to 
all array elements. The reason why the above statement 
failed to point to the next array element is because the ++ 
operator attempted to change the value of numbers, 
which  is  a  constant  pointer.  Any  valid  arithmetic 
operation which doesn’t attempt to change the value of 
numbers  can  point to  other  elements  of  the  array  as 
well. Let us modify the above increment statement by this 
one: 
 
Both  the  statements  on  Line  1  and  Line  2  add 
sizeof(int) to the value of numbers. The only 
difference  between  them  is,  the  statement  on  Line  2 
doesn’t attempt to change the value of numbers while the 
statement on Line 1 does. Therefore, the statement on 
Line  2  is  legal  and  it  points  to  the  second  element  of 
numbers array. If we dereference it, the second element 
of numbers  array  will  be  returned.  For  instance,  the 
following  statement  prints  the  value  of  the  second 
element of the array: 
 
And  the  following  statement  changes  the  value  of  the 
fourth element of the array to 32. 
 
By  using  the  name  of  the  array,  we  accessed  and 
manipulated the array elements which we wanted. It was 
fascinating, right? The above example shows how one-
dimensional  arrays  can  be  used  as  pointers  and  the 
associated  restrictions  while  doing  so.  Can  we  say that 
one-dimensional arrays and pointers are the same except 
the  arithmetic  restrictions  on  array  names?  Not  really. 
There are subtle differences between them. We can pick 
two, for instance. The first one is the difference in the 
memory address of pointers themselves and the memory 
address  referred  by  array  names.  The  other  is 
initialization. 
We  have  seen  that  normal  pointers  have  their  own 
memory space allocated for them. However, a separate 
memory space is not allocated for array names, although 
they  are  considered  as  pointers.  The  memory  address 
associated  with  array  names  is  that  of  the  first  array 
element.  In  general, the  memory  returned  by  the  address  of 
operator on one-dimensional array names is the same the memory 
address of the first element. 
We have also seen that arrays can be initialized during or 
after declaration (except for character arrays) using braces. 
However, pointers cannot be initialized with braces even 
if they can be used as arrays. 
Having  the  above  differences  between  arrays  and 
pointers,  let  us  now  consider  character  arrays  in 
accordance with the above concepts. Do you remember 
what we said about character arrays in chapter two? We 
said that they are given special consideration in C++. One 
of the ways in which they are treated differently is, the 
whole character array can be printed by printing the array 
name. With the concept in mind, let us now investigate 
what made character arrays so special in C++. For this, 
we will consider the following character array.  

By: Asaye Chemeda Email: [email protected] 35

 
To check that the array name program only refers to 
the  address  of  the  first  element,  we  can  see  the  truth 
values of the following logical statements. 
 
From  the  above,  only  the  statement  on  Line  1  returns 
true.  Hence,  the name program  only  points  to  the 
first elements of the array. The following statements will 
print characters ‘C’, ‘+’ and ‘+’ respectively. 
 
Any of the elements of the character array can also be 
manipulated by using the dereferencing operator. 
So far, we are getting what we expected and everything 
seems  normal.  The  character  array  name program  is 
behaving just like any other array name. If so, what do you 
expect the output of the following statement will be? 
 
If the character array name program behaves like other 
array  names,  what  is  printed  by  the  above  statement 
would be the memory address of the first program 
array element. But, that is not what will be printed. All the 
array elements, and probably additional characters, will 
be  printed.  Even  if  we  expect  memory  address  of  the 
character ‘C’ to be printed, all the characters in the array 
will printed as a string. Mysterious, isn’t it? 
The  reason  for  the  above  mystery  to  happen  will  be 
solved by analyzing property of the ‘<<’ operator. The 
way how the ‘<<’ operator will respond when it is called 
into action is implemented in the iostream.h file. In 
the iostream.h,  there  are  a  number  of  overloaded 
functions to handle the responses when this operator is 
called in a program. 
Recalling  our  discussion  on  functions  in  chapter  one, 
overloaded functions have the same name but different 
signatures. The overloaded function to handle the ‘<<’ 
operator is overloaded with several data types including 
pointers.  
Do  you  remember  rule  1  of  overloading  which  we 
discussed?  The  rule  can  be  summarized  as:  when  an 
overloaded function is called, the compiler tries to invoke 
the function with the best match formal parameter as the 
passed argument. Based on this rule, when pointers are 
passed to the function responding to calls made to ‘<<’ 
operator, there are two alternative overloaded functions 
with  pointer  formal  parameters  to  be  invoked.  One  of 
them has a data type for its formal parameter as const
void* while the other one has const char*. When 
names of non-character arrays are passed as an argument, 
the overloaded function with the const void* as a 
formal parameter data type will be invoked. As a result, 
the  memory  address  contained  in  the  passed  pointer, 
which  is  the  array  name,  will  be  printed  by  the  ‘<<’ 
operator.  
However, when the name of character arrays is passed, 
the overloaded function with const char* as a data 
type  for  the  formal  parameter  will  be  invoked.  This 
function doesn’t print the memory address contained in 
the  name  of  the  passed  character  array.  Rather,  all  the 
characters  in  the  array  until  the  null  character  is 
encountered will be printed. If the character array is not 
null-terminated, additional characters may also be printed. 
Mystery solved! 
After all, character arrays behave in the same way as other 
arrays. The separate functions which handle exclusively 
character  arrays,  however,  treat  them  differently  and 
create the illusion that character arrays are different from 
others.  
We have seen how one-dimensional arrays can be used as 
pointers. Now, let us see the reverse- how pointers can be 
used as one-dimensional arrays. Again, we will consider a 
fragment of a code. Consider the following string array 
and string pointer. 
 
In the above code fragment, the name of the string array, 
str, which is actually a pointer to the first element of the 
array, “C++” is assigned to a string pointer, p. If p is 
dereferenced  after  Line  3,  the  return  will  be  the  string 
“C++”. If you answer what the following statement prints 
correctly,  it  means  that  you  have  fresh  memory  of 
arithmetic operations on pointers. 
 
In  the  above  statement,  the  value  of p  pointer  is  pre-
incremented  by sizeof(string)  and  then 
dereferenced. The pre-increment will make p point to the 
second element of str array before being dereferenced. 
The  dereferencing  returns  the  value  of  the  second 
element of the str array. Therefore, the above statement 
prints the string “is”. 
Is that how a pointer is used as an array? If so, where is 
the array subscripting operator ([]) used? These are good 

By: Asaye Chemeda Email: [email protected] 36

questions.  Indeed,  accessing  array  elements  without 
pointers is characterized by the usage of indexing through 
the [] operator. The way the pointer p was used above 
to access the elements of str array doesn’t show that 
pointers can be used as arrays. 
Do  you  remember  how  name  of  array  was  used  as  a 
pointer to access array elements? The basic idea at that 
time was array name is a pointer and by dereferencing the 
array name with integer addition or subtraction, the array 
elements can be accessed and manipulated. Now, let us 
see how array elements are accessed by indexing using the 
array  name.  Since  indexing  starts  from  zero, str[0] 
refers  to  the  value  of  the  first  element  of str  array, 
str[1] refers to the second and so on.  
By  initializing  the p  pointer  with  array  name str,  we 
have synchronized them to refer to the memory address 
of the first element of str array. Now, let us try to use 
the pointer p as str the way that str could be used as 
p to access the array elements. If this is possible, i.e. if we 
can  access  and  manipulate  elements  of str  array  by 
indexing p  pointer  without  using  the  dereferencing 
operator, we can say that pointers can indeed be used as 
arrays. 
Of course, it is possible to access and manipulate elements 
of  one-dimensional  arrays  by  indexing  pointers.  For 
instance, p[0] refers to the value of the first element of 
str array. The other elements can also be accessed and 
manipulated in a similar manner. The following statement 
changes the third element of str array from “fun” to 
“awesome”. 
 
Note that, in the above statement, the array subscripting 
not the dereferencing operator was used on the pointer p 
to change the third str element. Note that using index of 2 
with pointers may not necessarily refer to the third array element. It 
only means the third element from which the pointer is initialized 
with the address of. For instance, if a pointer is initialized 
with the address of the second element of the array, using 
index of 2 with the pointer refers the fourth element of 
the array not the third. 
Don’t  you  feel  convinced  that  pointers  can  be  used as 
arrays?  Hopefully,  you  do.  Now,  think  about  details. 
Consider the following program and guess what will be 
printed by the cout statements. Note that p is initialized 
with the address of the second element of str array. If 
you  answered  both  of  them  correctly,  you  have 
completely  understood  what  we  discussed so  far  about 
pointers and arrays.  
Program 3.4[Correct].cpp 
 
In the above program, p is initialized with the address of 
the second element of str array. Therefore, the indexing 
for p starts from the second element of str array. Based 
on this, p[0] refers the string “is” and p[1] refers to 
the third element of str array. Thus, the output of the 
cout statement on line 9 is the string “awesome”. 
The array name, however, always refers to the memory 
address of the first element. When 1 is added to an array 
name and dereferenced, the second element of the array 
is always returned. The output of the cout statement on 
line 10 is, therefore, the string “is”. 
One-dimensional  arrays  and  pointers  can  be 
interchangeably  used  to  access  and  manipulate  array 
elements without much difference between them. Is this 
also the case for two-dimensional arrays? Can we apply 
what we discussed so far about pointers and arrays for 
two-dimensional  arrays  too?  The  answer  for  this  is a 
mixed  yes  and  no.  before  looking  into  how  two-
dimensional arrays can be used as pointers or vice-versa, 
let  us  see  how  elements  of  two-dimensional  arrays  are 
stored in the memory. 
When  we  consider  two-dimensional  arrays,  what  we 
normally visualize is simple data type variables arranged 
in two dimensions. If the array has (m+1) rows and (n+1) 
columns, we may expect it to be arranged as below in the 
memory. 
 
Figure 1: Two-dimensional array representation 
The question is: is this how two-dimensional arrays are 
actually stored in the memory? In two dimensions with 
rows and columns? Not really. Two-dimensional arrays 
are stored in the memory as one-dimensional arrays. The 
above two-dimensional array will be stored in the memory 
as: 

By: Asaye Chemeda Email: [email protected] 37

 
Figure 2: Equivalent one-dimensional array representation 
If two-dimensional arrays are stored in the memory as if 
they  are  one-dimensional  arrays,  don’t  you  think  the 
basics of how they could be used interchangeably with 
pointers is already explained? We can say so but it may 
not be as straight forward as it was for one-dimensional 
arrays. The details are therefore important.  
Let  us  start  discussing  from  what  the  name  of  a  two-
dimensional  array represents. In  one-dimensional  array, 
the  name  of  the  array  just  represents  a  scalar  pointer 
containing  the memory  address  of the  first  element. Is 
that so for two-dimensional arrays too? Not really. The 
name of a two-dimensional array is a pointer to the first 
element  of  a  one-dimensional  array  of  pointers.  The 
elements  in  this  array  of  pointers  are  the  memory 
addresses of the first elements in each row. When this is 
represented in diagram, we will have the following: 
 
Figure 3: Two-dimensional array direction 
The name of two dimensional array is, therefore, a pointer 
to a pointer. Even if the name of two-dimensional array 
is  a  pointer  to  a  pointer,  we  can’t  assign  it  to  a scalar 
pointer to pointer.  
Are you getting lost? Or is it getting interesting? May be, 
if  we  use  examples,  it  will be  easier  to  understand  and 
more  exciting.  Let  us  consider  the  following  array 
declaration: 
 
In the above statement, marks array is declared to have 
three  columns  and  is  initialized  with  six  elements.  The 
array will have two rows but the compiler is not interested 
in the number of rows. Between the array name and the 
array  elements,  there  is  an array  of  pointers.  The array 
name marks is a pointer to a pointer and doesn’t directly 
point  to  any  of  the  array  elements.  If marks  is 
dereferenced once, what is returned is a memory address 
not the first array element. To understand what marks 
points to, we can think of marks to be an array name for 
one-dimensional array of pointers with the following two 
elements. 
 
We can also consider the above two elements to be the 
array  names  for  the  first  and  second  rows  of  the  two-
dimensional marks array respectively. They are memory 
addresses themselves but they can be considered as names 
of  the  two  rows  of marks  array.  If  they  are  one-
dimensional array names, they refer to the same memory 
address  as  the  elements  they  point  to  without  having 
memory addresses of their own. 
If the array name marks can be considered to have the 
above two elements, the identifier marks is supposed to 
take  the  memory  address  of &marks[0][0].  As  an 
array  name  itself, &marks[0][0],  refers  to  the 
memory  address  of  the  first  element  of  the  two-
dimensional marks array. In other words, the array name 
marks  also  refers  to  the  memory  address  of  element 
marks[0][0].  Despite  this,  dereferencing marks 
only once, will not return the first element of the array. 
What  a  single  dereferencing  on  marks  returns  is  the 
address  of marks[0][0].  However,  if marks  is 
dereferenced  twice,  the  first  element  will  be  returned. 
Which means that the array name marks is a pointer to 
a  pointer.  The  following  logical  statement  will  return 
true. 
 
Even  if marks  is  a  pointer  to  a  pointer,  it  can’t  be 
assigned  to  a  scalar  pointer  to  pointer.  The  following 
statement will cause compilation error. 
 

By: Asaye Chemeda Email: [email protected] 38

The reason for the compilation error is that pp is a scalar 
pointer to pointer while marks is a pointer to an array of 
pointers. The above assignment is just like trying to assign 
an  array  variable  to  a  simple  data  type  variable.  If  the 
reason behind the  impossibility  of  above  assignment  is 
not clear, go through what we recently discussed about 
two-dimensional array names once again. Incorporating 
the above statements in a program with output statements 
and  analyzing  the  results  might  also  help  for  a  better 
understanding. 
If two-dimensional array names are pointers to an array 
of pointers, then how are we going to use them to access 
and  manipulate  array  elements  as  pointers?  Good 
question at the right time. There are two options for this. 
One of them is using the array name partially as an array 
and partially as a pointer. The other option is by using the 
array name completely as a pointer.  
In the first option, the array name will be used to access 
the  intermediate  array  of  pointers  by  using  the  array 
subscripting  operator.  After  this,  the  elements  of the 
intermediate array of pointers will be used to access and 
manipulate the array elements through pointer arithmetic 
and dereferencing. 
In the second option, the data type of the array name will 
be  casted  from  pointer  to  pointer  to  simply  a  pointer. 
Then, the casted array name will be used to access all the 
array  elements  through  pointer  arithmetic  and 
dereferencing  without  using  the  array  subscripting 
operators.  
Both of the above options will be discussed in detail one 
by  one.  Although  the  second  option  is  easier,  starting 
from the first option creates a smooth transition. 
We will again consider the marks two-dimensional array. 
Since the array has two rows, consider the array to be a 
set  of  two  one-dimensional  arrays  each  representing  a 
single row. We have said that we can consider the array 
name marks  to  be  an  identifier  for  one-dimensional 
array of pointers. Each element in the one-dimensional 
array of pointers is a pointer to the first element of each 
row. Since the actual two-dimensional array has two rows, 
the  one-dimensional  array  of  pointers  will  have  two 
elements. Now, we can write the marks array as follows: 
 
Note  that,  each  element  in  the  above  one-dimensional 
array of pointers is an array name for each row of the 
actual  two-dimensional marks  array.   If marks  is  an 
identifier  for  a  one-dimensional  array  of  two  elements, 
how can we write the two elements in terms of marks? 
It  is  easy,  right?  We  can  write  it  using  the  array 
subscripting operator as follows: 
 
Since  the  two  elements  in  the  above marks  array  are 
names  for  each  row,  we  can  also  write  the  following 
statements. 
 
You  see  how  the  name marks  along  with  the [] 
operator  is  used  as  a  name  for  each  row.  The  names 
marks[0]  and marks[1]  will  act  as  constant 
pointers. As long as we do not apply arithmetic operation 
which attempts to change their values, marks[0] and 
marks[1]  can  now  be  used  as  normal  pointers.  By 
dereferencing them, we can access and manipulate the all 
the array elements. For instance, the following program 
changes  the  value  of marks[0][1]  from 89.3  to 
92.9 and prints all the elements of marks array. 
Program 3.5[Correct].cpp 
 
If you have understood that marks along with a single 
[] operator with the row number inside is just an array 
name for each row and if you recall how names of one 
dimensional arrays (such as each row of marks array) can 
be  used  as  pointers,  the  above  program  is  straight 
forward.  The  output  of  the  above  program  is  shown 
below. 
 
Program 3.5 shows how name of two-dimensional array 
can be used to access and manipulated all the elements of 
the array by the combination of subscripting and pointer 
dereferencing.  Do  you  feel  that  you  understood  every 
piece  of  it?  Or  do  you  feel  that  have  some  doubts? 
Whichever your feeling is, you are ok. If you understood 
it,  proceed  to  what  we  are  going  to  discuss  next. 
Otherwise,  go  through  it  once  again,  write  your  own 
programs, analyze outputs from different angles and you 
will definitely say “it isn’t that difficult”.  

By: Asaye Chemeda Email: [email protected] 39

Now,  let  us  proceed  to  the  second  and  easier  way  to 
access all elements in two-dimensional arrays by using the 
array name as a pointer. In this approach, consider the 
two-dimensional  array  to  be  a  continuous  one-
dimensional array as shown in Fig. 2. The equivalent one-
dimensional array is formed by appending each row at the 
end of the previous row. Can you imagine what should 
also be done during the conversion from two-dimensional 
to one-dimensional array? Two basic changes should be 
made. 
The  first  change  should  be  the  data  type  of  the  array 
name, not the individual array elements. The name of a 
two-dimensional arrays is a pointer to array of pointers 
while  that  of  one-dimensional  arrays  is  a  pointer. 
Therefore, if the conversation is to be made, the data type 
of  the  array  name  should  be  casted  accordingly.  The 
casting can be done as follows: 
 
As  long  as  we  make  the  explicit  casting  as  above 
consistently, the arrayName can be used as just a name 
of one dimensional array, i.e., the array name will behave 
as a pointer not a pointer to array of pointers. Consider 
the following two dimensional array declaration: 
 
Without  casting,  the  array  name sum  is  a  pointer  to  a 
pointer. Remember, even if it is a pointer to a pointer, 
sum  cannot be  assigned to  a  scalar pointer  to  pointer. 
However, by explicitly casting it, we can make it behave 
just like an array name of a one dimensional array. We can 
imagine the above array to be as such: 
 
The following statement returns a value of 9, which is the 
value first element of sum array. 
 
Note  that,  in  the  above  statement  we  used  only  one 
dereferencing operator. Even so, we accessed the value of 
the first element. Had we tried this without casting sum 
to (int *), we would have only got the address of the 
element. The value of the second element, which is 4, can 
be returned by the following statement. 
 
Therefore,  by  casting  the  names  of  two-dimensional 
arrays,  we  can  use  them  as  constant  scalar  pointers. 
Although the casting is essential, it is not the only change 
which  should  be  applied  to  use  two-dimensional  array 
names as scalar pointers. In addition to casting, another 
change  should  also  be  made  while  converting  two-
dimensional  arrays  into  an  equivalent  one-dimensional 
array. Can you guess what that change could be? It is the 
index of each element. 
When  indexing  through []  operator  only  is  used  to 
access elements of two-dimensional arrays, the row and 
column  numbers  should  be  explicitly  stated.  However, 
when  the  two-dimensional  array  is  converted  to  an 
equivalent  one-dimensional  array,  there  will  only  be  a 
single  index-the  row  number.  As  a  result,  the  row  and 
column indexes which are supposed to access element in 
the two-dimensional array should be adjusted so that they 
can be used to access the same array element in the one-
dimensional array. 
When two-dimensional arrays are condensed to form a 
one-dimensional array, the equivalent single index to be 
used for accessing the elements is determined from three 
values: row and column numbers of the element in the 
two-dimensional array and number of columns. That is 
why it is always mandatory to explicitly specify the column 
number during the definition of two dimensional arrays.  
Conversion Rule: If a two-dimensional array has n columns, for 
indexing puroses, it can be considered as a one-dimensional array in 
which the element on the i
th row and j
th column in the two dimensional 
array becomes k
th element in the equivalent one-dimensional array, 
where k=i*n+j. 
If  we  apply  casting  and  if  we  implement  the  above 
conversion rule properly to access the right element, using 
two dimensional array names as pointers becomes as easy 
as it is for one-dimensional array names. Do you agree 
with this or do you have a different view? Before deciding, 
let us have a look at the following program. 
Program 3.6[Correct].cpp 
 
In  the  above  program,  a  two-dimensional  array sum 
having three columns is declared and initialized on line 6. 
The single index for the equivalent one-dimensional array 
k  is  defined  on  line  7.  Two  for-loops  were  used  to 
navigate  through  all  the  array  elements.  The  outer for-
loop with i counter is navigates across the row and the 
inner  for-loop  with j  counter  navigates  across  the 
column. If the array is to be converted to an equivalent 

By: Asaye Chemeda Email: [email protected] 40

one-dimensional array, the index to be used for this array 
(k) is calculated on line 10.  
The cout statement on line 11, prints two values. The 
first  one  prints  the  value  of  an  array  element  through 
indexing  only.  The  second  one  prints  the  same  value 
through  pointer  only.  When  an  element  of the  array is 
printed using pointer arithmetic, first the array name is 
casted. Then, the index in the equivalent one-dimensional 
array is added through pointer arithmetic to point to each 
array  element.  By  dereferencing,  the  value  of  the  array 
element  is  returned  and  printed.  By  the  way,  we  don’t 
need  two  for-loops  when  accessing  elements  of  two 
dimensional arrays through pointers. One for-loop which 
navigates through all the elements can also be used. Since 
the number of elements in the array is 9, the following 
single for-loop prints all the elements of sum array in the 
same way the above program did. 
 
What  do  you  think  the  problem  will  be  if  we  use  the 
following piece of code instead of the above one? In other 
words, what could go wrong if we use pointer increment 
instead  of  integer  addition as  in  the  following  piece  of 
code? 
 
If you recall, the legal pointer arithmetic operations on 
array names, the answer is pretty simple. Array names are 
constant  pointers  and  their  values  cannot  be  changed. 
Integer addition just adds an integer to the array name 
without  changing  the  memory  address  pointed  by  the 
name.  Integer  addition  through ++  operator,  however, 
attempts  to  change  value  of  the  memory  address 
contained in the array name, which is illegal. That is why 
the above piece of code is wrong. Clear enough?  
Aren’t  you  still  convinced  that  using  two-dimensional 
array names as pointers is not that difficult? What about 
after having the following formula? 
If a  is  the  name  of  a  two-dimensional  array  having n 
columns  and  a  base  data  type  of dataType,  element 
a[i][j] can equivalently be accessed and manipulated 
using  the  array  name  as  pointer  using  the  following 
formula: 
 
So simple. Using two-dimensional array names as pointers 
has been discussed to the detail we need for this chapter. 
But,  is  that  all  what  we  are  going  to  discuss  about 
pointers?  Not  really.  Pointers  are  one  of  the  powerful 
blessings of C++ and mastering them should be a virtue 
of someone who wants to be a decent programmer. 
Few more interesting concepts are remaining and we will 
proceed to next one. Trust me. Our persistence will pay 
off. 
Before starting the topic of “Arrays and pointers”, we said 
that any curiosity that you might have about pointers to 
pointers will get response in this topic. The time has now 
come  to  answer  what  the  applications  of  pointers  to 
pointers  are  in  C++  programming.  One  of  the 
applications of pointers to pointers comes into picture, 
when we use pointers as two-dimensional arrays. 
Remember  that  we  haven’t  yet  discussed  how  pointers 
can be used as two-dimensional arrays. Before proceeding 
to it, recalling the basics of two-dimensional array names 
might be advantageous. 
Two dimensional array names are pointers to an array of 
pointers.  Because  of  this,  the  array  name  cannot  be 
assigned  to  a  scalar  pointer  to  a  pointer.  The  array  of 
pointers stands between the name and array elements. As 
a result, the array elements cannot be directly accessed by 
only a single dereferencing of the array name.  
If  we  want  to  use  pointers  as  two-dimensional  arrays, 
there may be several options. One of them is by creating 
a pointer which is a replica of the property of the array 
name. There is also another option in which pointers to 
pointers can be used to create and used as dynamic arrays. 
Both the options will be covered in this chapter. 
In order to create a pointer with similar properties as a 
name of two-dimensional array, the pointer should be a 
pointer to an array of pointers. In addition, the elements 
in the array of pointers should point to the first element 
in each row of the two-dimensional array. If a pointer to 
pointer is declared in such a manner, it can be used as a 
two-dimensional array itself and the elements of the array 
can be accessed by subscripting. 
For a better understanding, let us consider the following 
two dimensional array. 
 
The above name array is a two-dimensional array with 11 
columns  and  four rows.  Each  string  literal  is  a  row by 
itself. The characters in the above array can be arranged 
as follows. 
 

By: Asaye Chemeda Email: [email protected] 41

If we want to use a pointer to pointer which can be used 
as a two-dimensional array, first we need to create an array 
of  pointers.  The  array  of  pointers  will  have  the  same 
number of elements as the number of rows in the name 
array. Let us declare the array of pointers as follows: 
 
Each  element  of  the  pointer  array p  should  now  be 
initialized with the memory address of the first element in 
each row of name array as follows: 
 
The scalar pointer to pointer, which can be used a two-
dimensional  array,  can  now  be  declared  and  initialized 
with the address of the first element of pointer array p. 
this is done as follows: 
 
The pointer pp is a pointer to an array of pointers. Isn’t 
pp a replica of the name array? Of course it is. Now, we 
can use subscripting on pp to access and manipulate any 
element  of  the name  array.  It  just  acts  as  a  two 
dimensional array. The following for-loop prints all the 
characters as they are written during the declaration of 
name array. 
 
The scalar pointer to pointer pp was just used as an array. 
You see what the application of pointers to pointers could 
be. They can be used as arrays provided that they point to 
an array of pointers having elements, which in turn point 
to the first elements in each row of a two-dimensional 
array.  
The  above  procedure shows  one  of  the  ways  in  which 
pointers can be used as two dimensional arrays. Before 
proceeding to the last topic of this chapter, let us recall 
what we postponed to do in this topic. Can you guess 
what that might be? It is about passing two-dimensional 
arrays to functions. We put off its discussion, remember? 
To pass two dimensional arrays to functions, we can use 
different approaches. We can cast the array and pass it as 
a scalar pointer. We can define array of pointers with each 
element pointing to the element in the first column of the 
two-dimensional  array.  Then,  we  can  pass  the  array 
pointers  to  a function  which  receives  pointer  arrays  or 
scalar pointers to pointers.  
The following program shows three different approaches 
to  pass  two  dimensional  arrays.  In  the  program,  three 
functions will be defined and all of them print the last 
character of the name array given above. 
Program 3.7[Correct].cpp 
 
In  the  above  program,  the name  array  is  passed  to 
print1  function  by  casting  it  to  a  scalar  character 
pointer  on  line  16.  The  formal  parameter  of print1 
function is a scalar pointer and through pointer arithmetic 
each  element  of  the name  array  can  be  accessed  and 
manipulated. 
An array of pointers p is declared on line 17 and initialized 
on  line  19.  Then,  this  array  of  pointer  is  passed  to 
print2 function on line 20. The formal parameter of 
print2  function  is  an  array  of  pointers  itself.  The 
elements  of name  array  can  now  be  accessed  and 
manipulated through a combination of subscripting and 
pointer arithmetic.  
The array of pointers p can also be passed to function 
which  receives  scalar  pointers  to  pointers  like  the 
print3  function.  Then,  through  subscripting,  the 
elements  of  the name  array  can  be  accessed  and 
manipulated.  
The output of the above program is displayed below. The 
output of all the three functions is the last character of the 
name array, which is ‘k’. 
 
Almost done. One important topic is remaining though. 
Before proceeding to the topic, let us refer to program 
3.7. In the program, the name array is declared with 11 
columns and initialized with four string literals (names). 

By: Asaye Chemeda Email: [email protected] 42

This means that any of the initializing string literals cannot 
have more than 10 characters (the remaining one column 
is  for  the  null  character).  In  other  words,  any  of the 
initializing names cannot have more than 10 characters. 
Such arrays in which their size is defined before compile-
time are known as static arrays. 
Now, assume you want to create a program which takes 
names  of  the  customers  of  the  company  that  you  are 
working at. How many columns will you allocate for the 
array which will store the names? 11 or 20 or how many? 
This  numbers  of  columns  may  be  too  small  for  some 
names. If having small number of columns is a problem, 
why not take a very large value for the column number so 
that there will not be a problem when any name is taken 
by the program? It seems a good solution. But, is it? If we 
declare the array with a large value for the array which is 
going  to store  names,  don’t  you  think  we  are  going to 
waste memory space when names with small number of 
characters are taken by the program?  
Then, why not leave mentioning the number of columns 
during  declaration?  That  is  not  an  option  because  the 
compiler won’t allow us. If using small number for the 
column may not store long names, if using large number 
of  columns  wastes  memory  space  and  if  leaving  the 
number of columns unmentioned is not an option, what 
could  be  the  best  solution?  The  solution  for  this  is 
creating  a  dynamic  array  with  dynamic  array  size.  In 
dynamic arrays, any of the array sizes are so flexible that 
they  can  be  determined  after  the  program  is  compiled.  
The following topic will explain it more.  
Dynamic memory allocation 
Throughout this chapter, we have been discussing about 
pointers. Among the various concepts we discussed, we 
have  seen  how  pointers  store  memory  addresses  of 
variables,  how  pointers  are  dereferenced  and  how 
pointers  can  be  used  as  arrays.  In  all  these  cases,  the 
pointers  are  useless  unless  there  is  a  variable  created 
beforehand. The interesting question is: if the variables 
can be manipulated without the use of pointers, why do 
we need to define additional data? 
Here is the answer. In C++ programming, memory space 
is allocated for all non-pointer variables during compile-
time. However, there may be variables which only require 
memory space depending on the environment during run-
time. Or variables which obtain their values during run-
time might be necessary within a program for efficiency 
purposes.  In  such  cases,  pointers  become  powerful 
options  for  accessing  a  memory  space  allocated  during 
run-time.  
The pointer variables which we had been dealing with in 
the  previous  topics  obtain  a  memory  space  during 
compile-time. Therefore, all non-pointer variables and the 
type of pointer variables which we discussed so far obtain 
the  memory  space  allocated  for  them  during  compile 
time. Such variables for which memory space is allocated 
for  them  during  compile  time  are  known  as static 
variables. And those variables for which memory space 
is  allocated  for  them  during  run-time  are  known  as 
dynamic variables. The fact which makes pointers very 
useful is that dynamic variables cannot be created without 
pointers. 
Then,  how  do  we  define  dynamic  variables?  Good 
question. In order to create dynamic variables in C++, a 
special  word  is  used.  Dynamic  variables  are  created  in 
C++ using the keyword new. If a variable is declared with 
new,  its  memory  is  allocated  during  run-time  and  the 
address of the allocated memory is returned. Therefore, 
the variable declared by the keyword new should always 
be a pointer. Note that dynamic memory space may not 
always be granted. 
Using new,  two  types  of  dynamic  variables  can  be 
created:  a  pointer  with  single  address  and  an  array  of 
pointers  with  multiple  addresses.  The  syntax  used  to 
create dynamic variables is as follows. 
Dynamic single variables are declared as follows. 
 
In the above declaration, a memory space sufficient for a 
data type of dataType is allocated during run-time and 
the address is returned to pointer. 
For array of dynamic variables, 
 
In the above declaration, a memory space sufficient for 
Size  number  of  elements  each  with  a  data  type  of 
dataType  is  allocated  during  run-time  and  the  base 
address is returned to pointerArray. 
After pointers or pointer arrays are created dynamically, 
the  elements  which  they  point  to  can  be  accessed  and 
manipulated  through  dereferencing.  Once,  a  variable  is 
defined using the keyword new, the memory space which 
is allocated for the variable should be de-allocated before 
using the same variable to obtain a new dynamic memory 
space. Otherwise, a situation known as memory leak will 
be created. This can be easily elaborated by the following 
code fragment. 
 
In  the  above  code  fragment,  a double  pointer p  is 
declared on line 1. A dynamic memory is allocated for the 
dynamic variable which is going to be pointed to by p on 

By: Asaye Chemeda Email: [email protected] 43

line 2. The value of the dynamic variable is initialized with 
30.28 on line 3. On line 4, the pointer p again obtains a 
dynamic memory space. On line 4, the value at the recent 
memory location pointed by p is initialized with a value 
of 38.73. Diagrammatically, this is depicted as follows. 
Let us say the addresses for the memory allocated on line 
2 and on line 4 are 100 and 200 respectively. 
 
Let us focus on what happened on line 4. Even if p was 
pointing  to  memory  address 100,  a  new  dynamic 
memory, with address of 200, is allocated and the address 
is returned to p. Even if the value in memory address 100 
may not be used after line 4, the memory address 100, 
can never be accessed. This situation is known as memory 
leak. The memory size of address 100 may be few bytes. 
However, thousands or millions of such leaks may result 
in running out of memory space and ultimate termination 
of the program. 
To avoid memory leaks, dynamic memory spaces can be 
de-allocated  using  the  keyword delete.  The  way  in 
which delete  is  used  depends  on  the  type  of  the 
dynamic  memory  to  be  de-allocated.  To  de-allocate 
memory  spaces  allocated  for  single  variables,  the 
following syntax is used. 
 
For de-allocation of memory spaces allocated for arrays 
of variables, the syntax is: 
 
We can improve the above code fragment as follows. 
 
The  keyword delete  only  de-allocates  the  allocated 
dynamic memory for future use. It has nothing to do with 
the pointers or pointer arrays. After the dynamic memory 
is de-allocated using delete, the pointers may still point 
to the memory address they used to point. In such cases, 
the pointers are said to be dangling. 
To avoid the risk of dangling pointers, the pointers are 
usually  assigned  with NULL  after  the  memory  is  de-
allocated. 
After  our  discussion  on  how  memory  is  allocated 
dynamically  during  program  execution,  let  us  see  how 
dynamic  arrays  are  created  in  C++.  It  may  be  useful 
recalling how pointers are used as arrays. 
Let  us  upgrade  program  3.7  so  that  a  user  will  be 
prompted to enter a name and let us store the entered 
characters  in  a  two-dimensional  dynamic  array  called 
pName. The values of the number of rows and columns 
will be obtained at run-time. As a result, both these values 
are  variables.  The  number  of  rows  will  be  denoted  by 
rows and the number of columns by columns. The 
value of rows, which represents the number of names 
that is going to be stored in the dynamic array, will be 
entered by the customer. The value of columns, which 
represents the number of characters in the names entered 
by  the  customer,  is  determined  from  the  length  of  the 
string which stores the entered names. 
To  create  two-dimensional dynamic  arrays,  we  need  to 
define pointers to pointers. Let us denote the pointer to 
pointer which will be used as a dynamic two-dimensional 
array  a  name  of pName.  Note  that  both pName  and 
*pName are pointers. 
To  create  a  two-dimensional  array, pName  will  be  an 
array of pointers. Each element in the array of pointers 
will be an array name to an array of characters. The array 
of characters will be the characters in the names entered 
by the customer. First, pName will be defined to be an 
array  of  pointers  with  dynamically  allocated  memory 
space. 
 
Each element of the pName array can be accessed and 
initialized  through  subscripting.  Note  that  the  value  of 
rows in the above declaration will be determined during 
program execution. Therefore, the number of names that 
the dynamic array is going to store will be determined at 
run  time?  Isn’t  this  an  elegant  way  of  optimizing  your 
memory space? Of course it is. More is yet to come. The 
number of columns will also be made to be dynamic. 
If i  represents  a  row  number,  memory  is  allocated 
dynamically  for  each  column  in  the  row  under 
consideration by using the following statement. 

By: Asaye Chemeda Email: [email protected] 44

 
After this definition, pName will become a dynamic two-
dimensional array and its elements can be accessed and 
manipulated through indexing.  
During  our  discussion  in  chapter  two,  we  said  that 
functions cannot return arrays. However, this will not be 
a problem anymore. Can you guess why? Because we have 
pointers.  Even  though  functions  cannot  return  arrays, 
they can return pointers. Obviously, pointers can act as 
arrays. The logic is simple now. If functions can return 
pointers and if pointers can act as arrays, why don’t we 
return arrays as pointers? You see another importance of 
pointers. In general, if a function has to return an array, a 
pointer can substitute the array and the pointer can be 
returned as an array. 
Let  us  incorporate  what  we  discussed  about  dynamic 
arrays and returning arrays as pointers in a program which 
improves the drawbacks that could happen if we use static 
arrays. Here is the program. 
Program 3.8[Correct].cpp 
 
In the above program, there are three functions including 
main function. The values of the variables rows and 
columns are obtained at run-time but the variables are 
made global so that every function can access them. 
In  the main  function,  a  pointer  to  pointer pName  is 
defined on line 8. The pointer will be used to create the 
dynamic array. On line 9, the customer is prompted to 
enter the number of names that he wants to enter. This is 
just to show the dynamic nature of the array which we are 
going to create by entering different numbers of names 
for the dynamic array to hold. The number which will be 
entered  by  the  user  will  be  the number  of  rows  in the 
array. Therefore, it will be stored in the rows variable. 
The purpose of the statement in line 11 will be explained 
in  the  next  chapter.  On  line  12,  a  dynamic  memory  is 
allocated for array of char pointers and the base address 
is  returned  to pName.  Each  element  in  the  array  of 
pointers  will  be  used  point  to  the  base  address  of the 
characters  in  a  single  name.  Therefore,  the  number of 
elements in this array of pointers will be equal to rows 
and the assignment to pName was made as such. 
On line 13, a function named print is called by passing 
pName  as  an  argument.  The  formal  parameter  of  the 
print function is also made to conform to the data type 
of  the  passed  argument.  Within print  function,  a 
pointer to pointer is defined and it is initialized by the 
pointer returned by read function. 
The read function takes a pointer to a pointer of char 
data type as a parameter. It is the read function which 
reads the names entered by the customer and stores them 
in  the  dynamic  array  accordingly.  Note  that,  since the 
read function returns a pointer to pointer, the return 
type  of  the  function  is  stated  as  such.  In  the read 
function, a string variable sName is declared on line 18. 
This variable takes the name of one customer. There are 
two-four loops within the function. The outer for-loop 
loops  across  the  rows  while  the  inner  for-loop  loops 
across all the characters in a given name. Within the outer 
for-loop, the customer is prompted to enter his name on 
line 20. The statement on line 21, which will be explained 
in detail in the next chapter, reads all the characters in a 
string  entered  by  the  customer  until  the  ‘Enter’  key  is 
pressed. The entered string will be stored in the sName 
variable. 
Here comes another dynamic nature of the array which 
we are going to create. The number of columns in a given 
row will be determined after determining the number of 
characters in the entered name. Isn’t this what we wanted 
to improve in program 3.7? The number of characters in 

By: Asaye Chemeda Email: [email protected] 45

the entered name is determined by determining the length 
of sName  as  it  is  done  on  line  22.  The  determined 
number of characters plus one space for the null character 
is then assigned to the columns variable. This means 
that the value of the columns variable is determined at 
run-time. On line 23, a dynamic memory is allocated for 
an array having number of elements equal to columns. 
This dynamic array will be the dynamic column for each 
row  of  the  two-dimensional  dynamic  array.  You  see, 
entering long names is not a problem anymore and no 
memory space is going to be wasted. The exact memory 
requirement will be allocated for any name entered.  
On the same line of the program, i.e. line 23, the array of 
pointers in name variable, which also refers to the same 
memory  address  as pName,  is  assigned  with  the  base 
address  of  the  dynamic  memory  allocated  for  each 
column with the help of the array subscripting operator 
[]. For instance, pName[i] contains the base memory 
address  of  the  array  of  characters  which  stores  the i
th 
name entered by the customer.  
After this, each column in the given row is assigned with 
the corresponding character in the sName string on line 
25. The sName string changes every time the customer 
enters a name and presses the ‘Enter’ key. On line 26, the 
last character in each row is assigned with null character. 
Remember that on line 22, one is added to the length of 
sName in the assignment to columns to accommodate 
the null character. After all names are entered and stored 
in  the  dynamic  array,  the  pointer  to  pointer name  is 
returned by the read function. This returned pointer to 
pointer is then used to assign another pointer to pointer 
defined in the print function. Through this pointer to 
pointer, all the names stored in the dynamic array can be 
accessed by indexing. A four loop and a while-loop inside 
the print  function  will  print  every  character  in  the 
entered names until a null character is encountered. How 
dynamic was that? 
There could also be other easier ways by which a program 
with  the  same  goal  as  program  3.8  can  be  written. 
However,  the  program  was  also  intended  to  show  the 
implementation  of  our  recent  discussion  on  dynamic 
arrays  and  returning  arrays  as  pointers.  Indeed,  the 
program  created  a  dynamic  array  which  improves  the 
efficiency of memory allocation. 
That is all for this chapter. It was relatively longer than the 
other chapters. But, wasn’t it worth? Since pointers are 
areas  in  C++  which  can  lead  even  a  professional 
programmer to write faulty programs which are difficult 
to bug, the time and the effort we spent in this chapter 
will be rewarded. Besides, pointers provide us the means 
by  which  we  can  manipulate  data  in  a  program  which 
other approaches may not be capable of. So, the devotion 
we put in this chapter is justified. 
Even  if  this  and  the  previous  chapters  covered  lots  of 
basic  components  in  C++  programming,  wring  an 
efficient  program  may  ask  a  lot  more.  As  we  have 
progressed  from  chapter  to  chapter,  we  have  gathered 
more  and  more  knowledge  that  we  need  to  have  as  a 
programmer. So, do you want to know more? I know your 
answer is also yes because ‘C++ is fun’. Isn’t it? Let us go 
to the next chapter then. 
 
 
  
 
 
 
 
 
 
 
 
Tags