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

CHAPTER THREE In the above declaration, the dataType , which can also

POINTERS be void, is usually the same as the data type of the


variable that the pointerVariable points to.
Introduction
The data types in C++ are broadly categorized into simple Once a pointer variable is defined, how it is then used for
data types, structured data types and pointers. We have data manipulation? Before answering this question, we
already seen the first two. In this chapter, we will deal will discuss about two operators which are often used
about the third categories of data types in C++, i.e., with pointers. They are the address of operator denoted
pointers. Their name is coined from the fact that these by the ampersand symbol, & and the dereferencing or
data types point to another data. Pointer variables, or at address or indirection operator denoted by the
shortly pointers, are data types which are derived based asterisk symbol,*. The address of operator returns the
on other data types. There is also no name associated with memory address of its operand while the dereferencing
the data type of pointers. However, they are considered operator returns the value stored at a given memory
to be a separate data types in C++. location. To understand this a bit more, let us see the
following piece of code.
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. In the above code, an integer variable x is defined and
These types of pointers can point to any variable with any initialized with a value of 100 on line 1. As you know,
data type. They can also be assigned with other pointers when values are declared, a memory space is allocated for
which point to any data type. the variables during compile time. Those memory
locations have addresses. Let us say that the memory
Since pointers refer to the memory addresses of other address where x is stored, amongst others, is 1000. Let us
variables, they are very powerful means for manipulation depict this diagrammatically as follows.
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 The above diagram shows that at memory location 1000,
program. an integer value of 100 is stored.

Defining Pointers On line 2, a pointer variable p is declared by using the *


Pointers take the same data type but different content symbol. Which means that the variable p will store
than the variables which they point to. If so, how are these memory address of another variable, i.e., p is declared to
pointer variables are defined? What makes them be point to another variable. The int data type that the
distinguished from non-pointer variables? pointer variable is declared by indicates that the pointer
will point to a variable with int data type. Again, a separate
Pointer variables are distinguished from other non-
memory location will be allocated for this variable. Let us
pointer variables by using the asterisk symbol, *, during
say the memory location allocated for p has an address of
their definition. If the asterisk symbol is put in front of a
1003. When we depict this graphically, as in the above
variable during its declaration, the compiler will consider
diagram, we will have the following.
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: 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: asayechemeda@yahoo.com 26


access memory address 1003 which is not yet initialized Program 3.1[Correct].cpp
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 When the above program is run, the resulting output is
memory address of p, which is 1003. In short, p is now shown below. Note that, the address results are machine
pointing to variable x. After this, the memory locations dependent and you may obtain different addresses than
those shown below.
will appear to be:

In the above diagram, the memory address 1003 now


What we confirmed from the above output is that (1) The
contains another memory address 1000, which is the
address of x can be obtained by either the address of
memory address of variable x. After the initialization on
operator & or by the pointer variable p which points to
line 3, the variable p points to a specific known address
the variable x (Line 9 of the program and line 1 of the output).
and you can use it without any harm to your computer.
(2) A memory location is also allocated for the pointer
On line 4, the value at address contained by variable p is variable p which can be obtained by the & operator (Line
assigned with value of 25 by using the dereferencing 11 of the program and line 2 of the output). (3) The value of the
operator *. The part on the left hand size of assignment variable x can be obtained from the variable itself or from
operator of the statement, *p, refers to the value stored its pointer variable p by using the dereferencing operator
at memory address contained by pointer variable p. The *. (Line 13 of the program and line 3 of the output). (4) The
memory address contained by p is 1000 and the value at value of the variable x can be changed by using the *
address 1000 was 100. Therefore, the statement on line 4 operator and its pointer variable p. (Line 15 of the program
changes this value to 25. Diagrammatically, what happens and line 4 of the output).
after line 4 is shown as follows:
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
In the above diagram, the value at address 1000 is now following string of questions. If pointers are variables, can
changed to 25. Note that, memory address 1003 still we perform arithmetic operations on them? If it is
contains the memory location of variable x and further possible, what do the results of arithmetic operations on
changes can be made through the same procedure. pointers refer to? Do the results even have any real
However, the pointer variable p can also be made to point purpose in programming? All these questions will be
to another variable. answered in the following topic.
The way how pointers manipulate data in C++ is as Pointer Arithmetic
simple as what we discussed above. But that is not all Besides being assigned with and compared to another
about pointers. Based on the above concept, we can pointer variable, only the following arithmetic operations
utilize pointers to access and manipulate data in different can be performed on pointers.
ways. Before proceeding to those details, dont you think
it is good if we can incorporate the above piece of code 1. Pointer variables can be incremented or
into a full program and see the results? If that is also your decremented.
thought, let us see the following program.
By: Asaye Chemeda Email: asayechemeda@yahoo.com 27
2. Integer values can be added or subtracted from otherwise of the addresses contained by pointers. For
pointers. instance, if p and q are two pointers,
3. One pointer variable can be deducted from
another pointer variable. p == q returns true if the memory address in p
is equal to that in q or false otherwise.
Note that any other arithmetic operation is prohibited on p < q returns true if the memory address in p is
pointers. Understanding the above arithmetic operations less than that in q or false otherwise.
to a modest detail is helpful and they will be discussed
p > q returns true if the memory address in p is
below.
greater than that in q or false otherwise.
Assigning pointer with another pointer or a value. A
Such pointer comparisons might be useful if we are
pointer is not only assigned or initialized with the help of
interested to know whether two pointers refer to the same
the & operator. A pointer can also be assigned or
memory address or not. However, the purpose of pointer
initialized with another pointer. After the assignment,
comparison is not limited to this and you can use the
both the assigned and the assigning pointers refer to the
concept whenever appropriate.
same memory location. Let us have a look at the following
piece of code. 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
On line 1, a character variable c is declared and initialized such depends on the data type of the pointer. For
with a character literal A. On line 2, pointers p1 and p2 character pointers which point to characters which always
are declared. On line 3, p1 is initialized with the address have 1byte size, an increment adds one to the pointer
of c. On line 4, p2 is assigned with p1. After line 4, both where as a decrement subtracts one from the pointer. For
p1 and p2 will point to c. What each line of the above integer pointers which point to int variables which
piece of code will do is graphically depicted as below. normally have 4byte size, an increment adds four to the
Note that the memory addresses are arbitrary. 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
Pointers of any data type can also be assigned with only Let us refer to the following piece of code.
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.
On line 1 of the above of code, character variables c1,
Comparison of pointer variables. A comparison can be c2 and c3 are declared and initialized with character
made between two pointers. In general, pointers can be literals A, B and C respectively. On line 2, a pointer
used in logical comparison statements. These pChar with char data type is declared and initialized with
comparisons, however, are based on the equality or 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: asayechemeda@yahoo.com 28
memory locations with addresses of 2000, 2001 and 2002 83 and 49 respectively. On line 2, a pointer pInt with
respectively and pChar is stored at memory address int data type is declared and initialized with address of i1.
2004. At this point, pChar and *pChar are equal to At this point, pInt points to i1. Since the memory size
2000 and A respectively. This is depicted in a diagram of int data types is normally 4bytes, each integer variable
as follows. 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.
When pChar is incremented on line 3, the memory This is depicted in a diagram as follows. The memory
address in pChar will be incremented by the amount of addresses are written for alternate cells to avoid
the memory size of a single character variable, which is 1. congestion of characters.
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 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
When pChar is incremented on line 4 one more time, not 11. Which means that pInt now points to the next
the memory address in pChar will be incremented by 1. int variable which is i2. Thus, pInt and *pInt
After the increment, the memory address in pChar are equal to 14 and 83 respectively. Diagrammatically,
becomes 2002. Which means that pChar now points to this is represented as:
c3. Thus, pChar and *pChar are equal to 2002
and C respectively. When this is put in diagram, we will
have:

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.
When pChar is decremented on line 5, the memory Which means that pInt now points to i3. Thus,
address in pChar will be decremented by 1 and becomes pInt and *pInt are equal to 18 and 49
2001. Which means that pChar now points to c2 respectively. When this is put in diagram, we will have:
again. Thus, pChar and *pChar are equal to 2001
and B 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.
Increment and decrement in int pointers
Let us refer to the following piece of code. Thus, pInt and *pInt are equal to 14 and 83
respectively. When this is put in diagram, we will have:

On line 1 of the above of code, int variables i1, i2 and Isnt the way that the compiler handles incrementing and
i3 are declared and initialized with integer values 75, decrementing operations on pointers fascinating? Indeed

By: Asaye Chemeda Email: asayechemeda@yahoo.com 29


it is. But, have you noted this? In the above examples we Now, let us see how we can take the above knowledge to
assumed that the variables are stored in contiguous our advantage to pass arrays to functions and manipulate
(interconnected) memory locations. But, is that always the the elements of the array. When a function call is made to
case? Not necessarily. Simple data type values may not be pass an array, let the calling function pass the identifier of
stored as such. As a result, it may be difficult to keep track the array. Let us make the corresponding argument on the
of the memory locations for variables belonging to simple formal parameter list of the called function to be a
data types and trying to use the incrementing and pointer. Which means that, during function call, the array
decrementing operators to access values of such data identifier, which is a pointer, will be assigned to the
types may result in wrong calculation results or data corresponding pointer variable in the called function.
corruption. If so, what is the importance of incrementing Inside the body of the called function, all the array
and decrementing pointers? elements can now be accessed and manipulated by
incrementing and decrementing the pointer which is
Here is the answer for the above question. Some data assigned by the array identifier. Dont you think it is a
types are stored in the main memory in a structured good strategy? Of course it is. This way of passing arrays
manner. Structured data types such as arrays are good to functions is termed as passing arrays by pointers and
example for this. When elements of arrays are stored in if the program is well-written, it is the neatest way to pass
the main memory, the compiler will allocate contiguous arrays. Note that, the changes made on the pointers of
memory locations for them. Therefore, if the address of array elements inside the body of the function is also
the first element is known, the address of the other reflected in the calling environment. The above way of
elements can easily be tracked based on the memory size passing arrays is applicable for one-dimensional arrays.
requirement for each element.
Passing two-dimensional arrays can also be done through
As you may recall, the identifier used for defining arrays pointers. But, let us keep discussing this concept aside
refers to the address of the first element. In other words, until we start dealing with the pointers and arrays topic.
the identifier of an array is a pointer to the first array element. The I feel that we have discussed lots of concepts and we need
identifier can be assigned to a pointer. Based on a pointer to take a break. Do you also feel the same? However, in
which is assigned with identifier of an array, the memory the meantime, let us write a program through which we
addresses of all the other elements can easily be obtained will be able to understand what we discussed so far about
through incrementing and decrementing. You see, that is arithmetic operations on pointers as well as about passing
where the incrementing and decrementing operations on arrays by pointers. Here is the program.
pointers become very useful.
Program 3.2 [Correct].cpp
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.

By: Asaye Chemeda Email: asayechemeda@yahoo.com 30


The above program calculates the cube roots of the first On line 22 of the program, the void cubeRt pointer is
five positive perfect cubes by the cubeRoot function casted or converted to double pointer and the casted
and prints the cube roots by the print function. We will pointer is assigned to a double pointer named x. Through
only discuss the important points in the program. pointer x, the elements of the array x can now be
accessed and printed by using the increment operator.
On line 11, the cubeRoot function is called and the
The part of the statement on line 24, *x++, means access
identifier of the cube array is passed as an argument.
the value stored at address contained by x and increment
Technically, what is passed as an argument is a pointer to
the pointer x to the next value.
the first element of the cube array. When the
cubeRoot function is invoked by this call, the first thing I hope the above example clears any doubts you might
the function is going to do is assigning its formal have regarding pointer incrementing and passing one-
parameter accordingly with the passed argument. In C++ dimensional arrays to functions as pointers. Remember,
statement, this assignment is represented as: we havent yet covered all the possible arithmetic
operations on pointers; two more are remaining.
Adding or subtracting integers from pointer
Isnt this how a pointer is declared initialized with another variables. If you understand how incrementing and
pointer? Of course it is. In the above declaration, we need decrementing of pointers is done, understanding how
to understand that the data type of c is double and it can adding or subtracting of integers is done is pretty easy. As
only be initialized with a pointer of only double data type. you know, when incrementing is done by the ++ operator,
After the above declaration the pointer c will contain the the value of the variable on which the incrementing is
memory address of the first element of the cube array. done will be increased by sizeof(base data type of the
variable). The keyword sizeof is a reserved C++ word
On line 17, the cube root of the value at address contained
used to return the size of the memory space allocated for
by c is calculated and stored in the same address
objects. The value sizeof(base data type) of may not
contained by c. On line 18, the pointer is incremented.
merely mean one. It may mean one for char pointers,
After each increment, the pointer c will point to the next
four for int pointers or eight for double pointers.
element in the contiguous memory location, i.e., the next
Adding an integer i to a pointer, therefore, means adding
element of cube array. The for-loop controls for how
i times size of the pointer variable. The same is true for
many times that the increment will be done. When the
subtracting integers. Let us see this through the following
loop is complete, all the elements of the cube array will
piece of code.
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
In the above piece of code, a double variable x is defined
first element of the changed cube array elements not those
and initialized on line 1. On line 2, a double pointer p is
elements given on line 10.
defined and initialized with the address of x. Say the
Note that the data type of the formal parameter of the address of x is 100. After line 2, the value of p will be 100.
print function is void. This means that, the cubeRt Double data types normally require 8bytes. A single
pointer is a void pointer which can be assigned with increment on pointer p by ++ will result in a value of p
another pointer which points to a variable of any data to be 108. However, on line 3, the value of p is increased
type. However, to access and manipulate the data by 10. What do you think will the value of p become after
contained by the cubeRt pointer, explicit type casting line 3 when the value of p after line 2 is 100? Are you
should be made. Type casting is conversion of one data saying 110? If you say so, you might have forgotten how
type into another. One way to do this in C++ is by putting incrementing of pointers is done.
the data type to be converted to within brackets in front
When 10 is added to a double data type pointer variable,
of the variable which we want to convert its data type as
the value of the pointer will be incremented by 10 times
it was done on line 22. However, type casting may not be
sizeof(double) (i.e., 8). In other words, when 10 is
applicable for conversion between some data types. Note
that the casting on line 22 could also be done by using the added to pointer p, the value of the pointer will be
static_cast key word and the data type to be casted incremented by 80. Therefore after line 3, the value of p
to within angled brackets as in the following statement: becomes 180.
Subtracting integers from pointers is also done in a similar
procedure.
By: Asaye Chemeda Email: asayechemeda@yahoo.com 31
Deducting two pointer variables. Two pointers next topic might not be necessary. Otherwise, go through
pointing to the same data type may also be deducted from the next topic for a better understanding.
each other. The difference between two pointers results
Multiple Indirection
in an integer value. The absolute value of the resulting
integer represents the number of objects of the base data Pointers are variables themselves and a memory location
type between the pointers. The difference between two is allocated for them. If a pointer stores the memory
pointers, however, cannot be assigned to another pointer location allocated for another pointer variable, the pointer
even if the difference is equal to zero. is pointing to another pointer variable. In C++, the
process of pointing at another pointer is known as
We have now seen the only possible arithmetic operations
multiple indirection. The pointer with multiple
on pointers. The following operations, amongst others,
indirection is known as pointer to a pointer. The process
are prohibited.
of multiple indirection can be repeated as many as we
Adding two pointers want although more than three multiple indirection is
Assigning non-zero values to pointers rarely used in programming.
Adding or subtracting floating-point data type Pointers to pointers can be defined in the same way as
values from pointers. other pointers with only one indirection. The only
Multiplying or dividing two pointers. difference is, as many asterisk symbols as the number of
indirections will be put between the pointer and data type
At this point, we have discussed the basics of pointers and
of the pointer. The data type of pointers with multiple
pointer operations. Let us proceed further and discuss
indirection will be the same as the data type of the target
other details. Have you ever imagined that there could
value.
also be array of pointers? Indeed, there are arrays of
pointers too. A pointer with two indirections is declared with the
following syntax.
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 In the above declaration, the two asterisk symbols
is the asterisk symbol should be used to tell the compiler between the pointerVariable and dataType
that the array is an array of pointers. For instance, an array indicate that the pointerVariable will point to
of int pointers x having 10 elements can be declared as another pointer.
follows. 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
What would x store if it was just an int array declared pointers to pointers is the same as simple pointers. The
without the asterisk? Ten integer values, right? Because of target value can also be accessed and manipulated by
the asterisk, however, x is declared as a pointer array and pointers to pointer by using as many indirection operators
it stores ten memory addresses with each memory address as they are used to define the pointer to pointer.
pointing to an int variable. After this declaration, x can
It is easy, right? If not, the following simple program will
be initialized with memory addresses of other variables. If
make it so.
we want to initialize the fourth element of x with the
address of an int variable y, we can write the following: Program 3.3[Correct].cpp

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

By: Asaye Chemeda Email: asayechemeda@yahoo.com 32


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

By: Asaye Chemeda Email: asayechemeda@yahoo.com 33


The above logical statement compares the equality
between numbers and the address of numbers[0].
Since the returned value is true, it means that Both the statements on Line 1 and Line 2 add
numbers contains the address of numbers[0]. Thus, sizeof(int) to the value of numbers. The only
numbers is a pointer. If numbers is dereferenced, it difference between them is, the statement on Line 2
gives the value of the first array element. The following doesnt attempt to change the value of numbers while the
logical statement will, therefore, return true. 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
The first array element can also be changed to another int of numbers array will be returned. For instance, the
value, say 15, by using the array name through the following statement prints the value of the second
following statement. element of the array:

So far so good. The array name, numbers, is behaving And the following statement changes the value of the
exactly the same as other regular pointers. Can we fourth element of the array to 32.
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 By using the name of the array, we accessed and
how it behaves. manipulated the array elements which we wanted. It was
First, let us apply the incrementing operation on fascinating, right? The above example shows how one-
numbers and let us point to the next element of the dimensional arrays can be used as pointers and the
array. Recall that incrementing pointers will make them associated restrictions while doing so. Can we say that
point to the next element in contiguous memory one-dimensional arrays and pointers are the same except
locations. Trying to point to the next element of the the arithmetic restrictions on array names? Not really.
numbers array through the following statement, There are subtle differences between them. We can pick
however, results in compilation error. 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.
Array names are not like other pointers, after all. Can you
guess what the reason for the compilation error could be? We have seen that normal pointers have their own
It is the ++ operator. Since the data type of the array is memory space allocated for them. However, a separate
int, the above statement attempted to increment the value memory space is not allocated for array names, although
of numbers by sizeof(int). But, array names are they are considered as pointers. The memory address
associated with array names is that of the first array
constant pointers and their values cannot be changed and
element. In general, the memory returned by the address of
they only point to the first array element. This rule is not
operator on one-dimensional array names is the same the memory
limited for only incrementing, any other arithmetic
address of the first element.
operation which attempts to change the value of an array
name is illegal. We can now conclude that array names are We have also seen that arrays can be initialized during or
pointers with restrictions. after declaration (except for character arrays) using braces.
However, pointers cannot be initialized with braces even
If incrementing and decrementing is illegal on array
if they can be used as arrays.
names, we may think that, they are useless to point to
other array elements than the first one. However, that is Having the above differences between arrays and
not true at all. Array names can also be used to point to pointers, let us now consider character arrays in
all array elements. The reason why the above statement accordance with the above concepts. Do you remember
failed to point to the next array element is because the ++ what we said about character arrays in chapter two? We
operator attempted to change the value of numbers, said that they are given special consideration in C++. One
which is a constant pointer. Any valid arithmetic of the ways in which they are treated differently is, the
operation which doesnt attempt to change the value of whole character array can be printed by printing the array
numbers can point to other elements of the array as name. With the concept in mind, let us now investigate
well. Let us modify the above increment statement by this what made character arrays so special in C++. For this,
one: we will consider the following character array.
By: Asaye Chemeda Email: asayechemeda@yahoo.com 34
with pointer formal parameters to be invoked. One of
them has a data type for its formal parameter as const
To check that the array name program only refers to void* while the other one has const char*. When
the address of the first element, we can see the truth names of non-character arrays are passed as an argument,
values of the following logical statements. 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.
From the above, only the statement on Line 1 returns
true. Hence, the name program only points to the However, when the name of character arrays is passed,
first elements of the array. The following statements will the overloaded function with const char* as a data
print characters C, + and + respectively. type for the formal parameter will be invoked. This
function doesnt 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
Any of the elements of the character array can also be null-terminated, additional characters may also be printed.
manipulated by using the dereferencing operator. Mystery solved!

So far, we are getting what we expected and everything After all, character arrays behave in the same way as other
seems normal. The character array name program is arrays. The separate functions which handle exclusively
behaving just like any other array name. If so, what do you character arrays, however, treat them differently and
expect the output of the following statement will be? create the illusion that character arrays are different from
others.
We have seen how one-dimensional arrays can be used as
If the character array name program behaves like other pointers. Now, let us see the reverse- how pointers can be
array names, what is printed by the above statement used as one-dimensional arrays. Again, we will consider a
would be the memory address of the first program fragment of a code. Consider the following string array
array element. But, that is not what will be printed. All the and string pointer.
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, isnt it?
In the above code fragment, the name of the string array,
The reason for the above mystery to happen will be str, which is actually a pointer to the first element of the
solved by analyzing property of the << operator. The
array, C++ is assigned to a string pointer, p. If p is
way how the << operator will respond when it is called
dereferenced after Line 3, the return will be the string
into action is implemented in the iostream.h file. In
C++. If you answer what the following statement prints
the iostream.h, there are a number of overloaded
correctly, it means that you have fresh memory of
functions to handle the responses when this operator is
arithmetic operations on pointers.
called in a program.
Recalling our discussion on functions in chapter one,
overloaded functions have the same name but different
In the above statement, the value of p pointer is pre-
signatures. The overloaded function to handle the <<
incremented by sizeof(string) and then
operator is overloaded with several data types including
pointers. dereferenced. The pre-increment will make p point to the
second element of str array before being dereferenced.
Do you remember rule 1 of overloading which we The dereferencing returns the value of the second
discussed? The rule can be summarized as: when an element of the str array. Therefore, the above statement
overloaded function is called, the compiler tries to invoke prints the string is.
the function with the best match formal parameter as the
passed argument. Based on this rule, when pointers are Is that how a pointer is used as an array? If so, where is
passed to the function responding to calls made to << the array subscripting operator ([]) used? These are good
operator, there are two alternative overloaded functions
By: Asaye Chemeda Email: asayechemeda@yahoo.com 35
questions. Indeed, accessing array elements without Program 3.4[Correct].cpp
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 doesnt 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 In the above program, p is initialized with the address of
array name. Since indexing starts from zero, str[0] the second element of str array. Therefore, the indexing
refers to the value of the first element of str array, for p starts from the second element of str array. Based
str[1] refers to the second and so on. on this, p[0] refers the string is and p[1] refers to
the third element of str array. Thus, the output of the
By initializing the p pointer with array name str, we cout statement on line 9 is the string awesome.
have synchronized them to refer to the memory address
of the first element of str array. Now, let us try to use The array name, however, always refers to the memory
the pointer p as str the way that str could be used as address of the first element. When 1 is added to an array
name and dereferenced, the second element of the array
p to access the array elements. If this is possible, i.e. if we
is always returned. The output of the cout statement on
can access and manipulate elements of str array by
line 10 is, therefore, the string is.
indexing p pointer without using the dereferencing
operator, we can say that pointers can indeed be used as One-dimensional arrays and pointers can be
arrays. interchangeably used to access and manipulate array
elements without much difference between them. Is this
Of course, it is possible to access and manipulate elements also the case for two-dimensional arrays? Can we apply
of one-dimensional arrays by indexing pointers. For what we discussed so far about pointers and arrays for
instance, p[0] refers to the value of the first element of two-dimensional arrays too? The answer for this is a
str array. The other elements can also be accessed and mixed yes and no. before looking into how two-
manipulated in a similar manner. The following statement dimensional arrays can be used as pointers or vice-versa,
changes the third element of str array from fun to let us see how elements of two-dimensional arrays are
awesome. stored in the memory.
When we consider two-dimensional arrays, what we
normally visualize is simple data type variables arranged
Note that, in the above statement, the array subscripting in two dimensions. If the array has (m+1) rows and (n+1)
not the dereferencing operator was used on the pointer p columns, we may expect it to be arranged as below in the
memory.
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.
Dont you feel convinced that pointers can be used as
arrays? Hopefully, you do. Now, think about details. Figure 1: Two-dimensional array representation
Consider the following program and guess what will be
The question is: is this how two-dimensional arrays are
printed by the cout statements. Note that p is initialized
actually stored in the memory? In two dimensions with
with the address of the second element of str array. If
rows and columns? Not really. Two-dimensional arrays
you answered both of them correctly, you have
are stored in the memory as one-dimensional arrays. The
completely understood what we discussed so far about
above two-dimensional array will be stored in the memory
pointers and arrays. as:
By: Asaye Chemeda Email: asayechemeda@yahoo.com 36
is a pointer to a pointer, we cant 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 doesnt 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
Figure 2: Equivalent one-dimensional array representation points to, we can think of marks to be an array name for
one-dimensional array of pointers with the following two
If two-dimensional arrays are stored in the memory as if
elements.
they are one-dimensional arrays, dont you think the
basics of how they could be used interchangeably with
pointers is already explained? We can say so but it may
We can also consider the above two elements to be the
not be as straight forward as it was for one-dimensional
array names for the first and second rows of the two-
arrays. The details are therefore important.
dimensional marks array respectively. They are memory
Let us start discussing from what the name of a two- addresses themselves but they can be considered as names
dimensional array represents. In one-dimensional array, of the two rows of marks array. If they are one-
the name of the array just represents a scalar pointer dimensional array names, they refer to the same memory
containing the memory address of the first element. Is address as the elements they point to without having
that so for two-dimensional arrays too? Not really. The memory addresses of their own.
name of a two-dimensional array is a pointer to the first If the array name marks can be considered to have the
element of a one-dimensional array of pointers. The above two elements, the identifier marks is supposed to
elements in this array of pointers are the memory take the memory address of &marks[0][0]. As an
addresses of the first elements in each row. When this is
array name itself, &marks[0][0], refers to the
represented in diagram, we will have the following:
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 cant be


assigned to a scalar pointer to pointer. The following
Figure 3: Two-dimensional array direction statement will cause compilation error.
The name of two dimensional array is, therefore, a pointer
to a pointer. Even if the name of two-dimensional array

By: Asaye Chemeda Email: asayechemeda@yahoo.com 37


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 Since the two elements in the above marks array are
an array variable to a simple data type variable. If the names for each row, we can also write the following
reason behind the impossibility of above assignment is statements.
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
You see how the name marks along with the []
and analyzing the results might also help for a better
operator is used as a name for each row. The names
understanding.
marks[0] and marks[1] will act as constant
If two-dimensional array names are pointers to an array pointers. As long as we do not apply arithmetic operation
of pointers, then how are we going to use them to access which attempts to change their values, marks[0] and
and manipulate array elements as pointers? Good marks[1] can now be used as normal pointers. By
question at the right time. There are two options for this. dereferencing them, we can access and manipulate the all
One of them is using the array name partially as an array the array elements. For instance, the following program
and partially as a pointer. The other option is by using the changes the value of marks[0][1] from 89.3 to
array name completely as a pointer. 92.9 and prints all the elements of marks array.
In the first option, the array name will be used to access Program 3.5[Correct].cpp
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.
If you have understood that marks along with a single
Since the array has two rows, consider the array to be a
[] operator with the row number inside is just an array
set of two one-dimensional arrays each representing a
single row. We have said that we can consider the array name for each row and if you recall how names of one
name marks to be an identifier for one-dimensional dimensional arrays (such as each row of marks array) can
array of pointers. Each element in the one-dimensional be used as pointers, the above program is straight
array of pointers is a pointer to the first element of each forward. The output of the above program is shown
row. Since the actual two-dimensional array has two rows, below.
the one-dimensional array of pointers will have two
elements. Now, we can write the marks array as follows:
Program 3.5 shows how name of two-dimensional array
can be used to access and manipulated all the elements of
Note that, each element in the above one-dimensional the array by the combination of subscripting and pointer
array of pointers is an array name for each row of the dereferencing. Do you feel that you understood every
actual two-dimensional marks array. If marks is an piece of it? Or do you feel that have some doubts?
identifier for a one-dimensional array of two elements, Whichever your feeling is, you are ok. If you understood
how can we write the two elements in terms of marks? it, proceed to what we are going to discuss next.
It is easy, right? We can write it using the array Otherwise, go through it once again, write your own
subscripting operator as follows: programs, analyze outputs from different angles and you
will definitely say it isnt that difficult.
By: Asaye Chemeda Email: asayechemeda@yahoo.com 38
Now, let us proceed to the second and easier way to dimensional arrays into an equivalent one-dimensional
access all elements in two-dimensional arrays by using the array. Can you guess what that change could be? It is the
array name as a pointer. In this approach, consider the index of each element.
two-dimensional array to be a continuous one-
When indexing through [] operator only is used to
dimensional array as shown in Fig. 2. The equivalent one-
access elements of two-dimensional arrays, the row and
dimensional array is formed by appending each row at the
column numbers should be explicitly stated. However,
end of the previous row. Can you imagine what should
when the two-dimensional array is converted to an
also be done during the conversion from two-dimensional
equivalent one-dimensional array, there will only be a
to one-dimensional array? Two basic changes should be
single index-the row number. As a result, the row and
made.
column indexes which are supposed to access element in
The first change should be the data type of the array the two-dimensional array should be adjusted so that they
name, not the individual array elements. The name of a can be used to access the same array element in the one-
two-dimensional arrays is a pointer to array of pointers dimensional array.
while that of one-dimensional arrays is a pointer.
When two-dimensional arrays are condensed to form a
Therefore, if the conversation is to be made, the data type
one-dimensional array, the equivalent single index to be
of the array name should be casted accordingly. The
used for accessing the elements is determined from three
casting can be done as follows:
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
As long as we make the explicit casting as above number during the definition of two dimensional arrays.
consistently, the arrayName can be used as just a name
of one dimensional array, i.e., the array name will behave
Conversion Rule: If a two-dimensional array has n columns, for
indexing puroses, it can be considered as a one-dimensional array in
as a pointer not a pointer to array of pointers. Consider
which the element on the ith row and jth column in the two dimensional
the following two dimensional array declaration:
array becomes kth element in the equivalent one-dimensional array,
where k=i*n+j.
Without casting, the array name sum is a pointer to a If we apply casting and if we implement the above
pointer. Remember, even if it is a pointer to a pointer, conversion rule properly to access the right element, using
sum cannot be assigned to a scalar pointer to pointer. two dimensional array names as pointers becomes as easy
However, by explicitly casting it, we can make it behave as it is for one-dimensional array names. Do you agree
just like an array name of a one dimensional array. We can with this or do you have a different view? Before deciding,
imagine the above array to be as such: let us have a look at the following program.
Program 3.6[Correct].cpp

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.
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
Therefore, by casting the names of two-dimensional
k is defined on line 7. Two for-loops were used to
arrays, we can use them as constant scalar pointers.
navigate through all the array elements. The outer for-
Although the casting is essential, it is not the only change
loop with i counter is navigates across the row and the
which should be applied to use two-dimensional array
inner for-loop with j counter navigates across the
names as scalar pointers. In addition to casting, another
column. If the array is to be converted to an equivalent
change should also be made while converting two-

By: Asaye Chemeda Email: asayechemeda@yahoo.com 39


one-dimensional array, the index to be used for this array blessings of C++ and mastering them should be a virtue
(k) is calculated on line 10. of someone who wants to be a decent programmer.
The cout statement on line 11, prints two values. The Few more interesting concepts are remaining and we will
first one prints the value of an array element through proceed to next one. Trust me. Our persistence will pay
indexing only. The second one prints the same value off.
through pointer only. When an element of the array is Before starting the topic of Arrays and pointers, we said
printed using pointer arithmetic, first the array name is that any curiosity that you might have about pointers to
casted. Then, the index in the equivalent one-dimensional pointers will get response in this topic. The time has now
array is added through pointer arithmetic to point to each come to answer what the applications of pointers to
array element. By dereferencing, the value of the array pointers are in C++ programming. One of the
element is returned and printed. By the way, we dont applications of pointers to pointers comes into picture,
need two for-loops when accessing elements of two when we use pointers as two-dimensional arrays.
dimensional arrays through pointers. One for-loop which
navigates through all the elements can also be used. Since Remember that we havent yet discussed how pointers
the number of elements in the array is 9, the following can be used as two-dimensional arrays. Before proceeding
single for-loop prints all the elements of sum array in the to it, recalling the basics of two-dimensional array names
same way the above program did. 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
What do you think the problem will be if we use the pointers stands between the name and array elements. As
following piece of code instead of the above one? In other a result, the array elements cannot be directly accessed by
words, what could go wrong if we use pointer increment only a single dereferencing of the array name.
instead of integer addition as in the following piece of If we want to use pointers as two-dimensional arrays,
code? 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.
If you recall, the legal pointer arithmetic operations on
array names, the answer is pretty simple. Array names are In order to create a pointer with similar properties as a
constant pointers and their values cannot be changed. name of two-dimensional array, the pointer should be a
Integer addition just adds an integer to the array name pointer to an array of pointers. In addition, the elements
without changing the memory address pointed by the in the array of pointers should point to the first element
name. Integer addition through ++ operator, however, in each row of the two-dimensional array. If a pointer to
attempts to change value of the memory address pointer is declared in such a manner, it can be used as a
contained in the array name, which is illegal. That is why two-dimensional array itself and the elements of the array
the above piece of code is wrong. Clear enough? can be accessed by subscripting.
Arent you still convinced that using two-dimensional For a better understanding, let us consider the following
array names as pointers is not that difficult? What about two dimensional array.
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 The above name array is a two-dimensional array with 11
formula: columns and four rows. Each string literal is a row by
itself. The characters in the above array can be arranged
as follows.
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

By: Asaye Chemeda Email: asayechemeda@yahoo.com 40


If we want to use a pointer to pointer which can be used The following program shows three different approaches
as a two-dimensional array, first we need to create an array to pass two dimensional arrays. In the program, three
of pointers. The array of pointers will have the same functions will be defined and all of them print the last
number of elements as the number of rows in the name character of the name array given above.
array. Let us declare the array of pointers as follows:
Program 3.7[Correct].cpp

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. Isnt


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 In the above program, the name array is passed to
dimensional array. The following for-loop prints all the print1 function by casting it to a scalar character
characters as they are written during the declaration of pointer on line 16. The formal parameter of print1
name array. 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
The scalar pointer to pointer pp was just used as an array. print2 function is an array of pointers itself. The
You see what the application of pointers to pointers could elements of name array can now be accessed and
be. They can be used as arrays provided that they point to manipulated through a combination of subscripting and
an array of pointers having elements, which in turn point pointer arithmetic.
to the first elements in each row of a two-dimensional The array of pointers p can also be passed to function
array. which receives scalar pointers to pointers like the
The above procedure shows one of the ways in which print3 function. Then, through subscripting, the
pointers can be used as two dimensional arrays. Before elements of the name array can be accessed and
proceeding to the last topic of this chapter, let us recall manipulated.
what we postponed to do in this topic. Can you guess The output of the above program is displayed below. The
what that might be? It is about passing two-dimensional output of all the three functions is the last character of the
arrays to functions. We put off its discussion, remember? name array, which is k.
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
Almost done. One important topic is remaining though.
two-dimensional array. Then, we can pass the array
Before proceeding to the topic, let us refer to program
pointers to a function which receives pointer arrays or
3.7. In the program, the name array is declared with 11
scalar pointers to pointers.
columns and initialized with four string literals (names).

By: Asaye Chemeda Email: asayechemeda@yahoo.com 41


This means that any of the initializing string literals cannot type of pointer variables which we discussed so far obtain
have more than 10 characters (the remaining one column the memory space allocated for them during compile
is for the null character). In other words, any of the time. Such variables for which memory space is allocated
initializing names cannot have more than 10 characters. for them during compile time are known as static
Such arrays in which their size is defined before compile- variables. And those variables for which memory space
time are known as static arrays. is allocated for them during run-time are known as
dynamic variables. The fact which makes pointers very
Now, assume you want to create a program which takes
useful is that dynamic variables cannot be created without
names of the customers of the company that you are
pointers.
working at. How many columns will you allocate for the
array which will store the names? 11 or 20 or how many? Then, how do we define dynamic variables? Good
This numbers of columns may be too small for some question. In order to create dynamic variables in C++, a
names. If having small number of columns is a problem, special word is used. Dynamic variables are created in
why not take a very large value for the column number so C++ using the keyword new. If a variable is declared with
that there will not be a problem when any name is taken new, its memory is allocated during run-time and the
by the program? It seems a good solution. But, is it? If we address of the allocated memory is returned. Therefore,
declare the array with a large value for the array which is the variable declared by the keyword new should always
going to store names, dont you think we are going to be a pointer. Note that dynamic memory space may not
waste memory space when names with small number of always be granted.
characters are taken by the program?
Using new, two types of dynamic variables can be
Then, why not leave mentioning the number of columns created: a pointer with single address and an array of
during declaration? That is not an option because the pointers with multiple addresses. The syntax used to
compiler wont allow us. If using small number for the create dynamic variables is as follows.
column may not store long names, if using large number
of columns wastes memory space and if leaving the Dynamic single variables are declared as follows.
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 In the above declaration, a memory space sufficient for a
dynamic arrays, any of the array sizes are so flexible that data type of dataType is allocated during run-time and
they can be determined after the program is compiled. the address is returned to pointer.
The following topic will explain it more. For array of dynamic variables,
Dynamic memory allocation
Throughout this chapter, we have been discussing about In the above declaration, a memory space sufficient for
pointers. Among the various concepts we discussed, we Size number of elements each with a data type of
have seen how pointers store memory addresses of dataType is allocated during run-time and the base
variables, how pointers are dereferenced and how address is returned to pointerArray.
pointers can be used as arrays. In all these cases, the
pointers are useless unless there is a variable created After pointers or pointer arrays are created dynamically,
beforehand. The interesting question is: if the variables the elements which they point to can be accessed and
can be manipulated without the use of pointers, why do manipulated through dereferencing. Once, a variable is
we need to define additional data? defined using the keyword new, the memory space which
is allocated for the variable should be de-allocated before
Here is the answer. In C++ programming, memory space using the same variable to obtain a new dynamic memory
is allocated for all non-pointer variables during compile- space. Otherwise, a situation known as memory leak will
time. However, there may be variables which only require be created. This can be easily elaborated by the following
memory space depending on the environment during run- code fragment.
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 In the above code fragment, a double pointer p is
the previous topics obtain a memory space during declared on line 1. A dynamic memory is allocated for the
compile-time. Therefore, all non-pointer variables and the dynamic variable which is going to be pointed to by p on
By: Asaye Chemeda Email: asayechemeda@yahoo.com 42
line 2. The value of the dynamic variable is initialized with The keyword delete only de-allocates the allocated
30.28 on line 3. On line 4, the pointer p again obtains a dynamic memory for future use. It has nothing to do with
dynamic memory space. On line 4, the value at the recent the pointers or pointer arrays. After the dynamic memory
memory location pointed by p is initialized with a value is de-allocated using delete, the pointers may still point
of 38.73. Diagrammatically, this is depicted as follows. to the memory address they used to point. In such cases,
Let us say the addresses for the memory allocated on line the pointers are said to be dangling.
2 and on line 4 are 100 and 200 respectively.
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
Let us focus on what happened on line 4. Even if p was represents the number of characters in the names entered
pointing to memory address 100, a new dynamic by the customer, is determined from the length of the
memory, with address of 200, is allocated and the address string which stores the entered names.
is returned to p. Even if the value in memory address 100 To create two-dimensional dynamic arrays, we need to
may not be used after line 4, the memory address 100, define pointers to pointers. Let us denote the pointer to
can never be accessed. This situation is known as memory pointer which will be used as a dynamic two-dimensional
leak. The memory size of address 100 may be few bytes. array a name of pName. Note that both pName and
However, thousands or millions of such leaks may result *pName are pointers.
in running out of memory space and ultimate termination
of the program. To create a two-dimensional array, pName will be an
array of pointers. Each element in the array of pointers
To avoid memory leaks, dynamic memory spaces can be will be an array name to an array of characters. The array
de-allocated using the keyword delete. The way in of characters will be the characters in the names entered
which delete is used depends on the type of the by the customer. First, pName will be defined to be an
dynamic memory to be de-allocated. To de-allocate array of pointers with dynamically allocated memory
memory spaces allocated for single variables, the space.
following syntax is used.

Each element of the pName array can be accessed and


For de-allocation of memory spaces allocated for arrays initialized through subscripting. Note that the value of
of variables, the syntax is: 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
We can improve the above code fragment as follows. run time? Isnt 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: asayechemeda@yahoo.com 43


In the above program, there are three functions including
main function. The values of the variables rows and
After this definition, pName will become a dynamic two-
columns are obtained at run-time but the variables are
dimensional array and its elements can be accessed and
manipulated through indexing. made global so that every function can access them.

During our discussion in chapter two, we said that In the main function, a pointer to pointer pName is
functions cannot return arrays. However, this will not be defined on line 8. The pointer will be used to create the
a problem anymore. Can you guess why? Because we have dynamic array. On line 9, the customer is prompted to
pointers. Even though functions cannot return arrays, enter the number of names that he wants to enter. This is
they can return pointers. Obviously, pointers can act as just to show the dynamic nature of the array which we are
arrays. The logic is simple now. If functions can return going to create by entering different numbers of names
pointers and if pointers can act as arrays, why dont we for the dynamic array to hold. The number which will be
return arrays as pointers? You see another importance of entered by the user will be the number of rows in the
pointers. In general, if a function has to return an array, a array. Therefore, it will be stored in the rows variable.
pointer can substitute the array and the pointer can be
returned as an array. The purpose of the statement in line 11 will be explained
in the next chapter. On line 12, a dynamic memory is
Let us incorporate what we discussed about dynamic allocated for array of char pointers and the base address
arrays and returning arrays as pointers in a program which is returned to pName. Each element in the array of
improves the drawbacks that could happen if we use static
pointers will be used point to the base address of the
arrays. Here is the program.
characters in a single name. Therefore, the number of
Program 3.8[Correct].cpp 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. Isnt this what we wanted
to improve in program 3.7? The number of characters in

By: Asaye Chemeda Email: asayechemeda@yahoo.com 44


the entered name is determined by determining the length by which we can manipulate data in a program which
of sName as it is done on line 22. The determined other approaches may not be capable of. So, the devotion
number of characters plus one space for the null character we put in this chapter is justified.
is then assigned to the columns variable. This means
Even if this and the previous chapters covered lots of
that the value of the columns variable is determined at
basic components in C++ programming, wring an
run-time. On line 23, a dynamic memory is allocated for
efficient program may ask a lot more. As we have
an array having number of elements equal to columns.
progressed from chapter to chapter, we have gathered
This dynamic array will be the dynamic column for each
more and more knowledge that we need to have as a
row of the two-dimensional dynamic array. You see,
programmer. So, do you want to know more? I know your
entering long names is not a problem anymore and no
answer is also yes because C++ is fun. Isnt it? Let us go
memory space is going to be wasted. The exact memory
to the next chapter then.
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 ith
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, wasnt 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: Asaye Chemeda Email: asayechemeda@yahoo.com 45

You might also like