0% found this document useful (0 votes)
3 views

Chapter 6 Computer Programmingodp

Chapter Six of the document covers pointers in C++, including their declaration, initialization, and arithmetic. It explains how pointers relate to arrays, pointers to pointers, and pointers to functions, along with dynamic memory management. Key concepts include the use of the address operator (&), dereference operator (*), and the implications of pointer arithmetic.

Uploaded by

birhanua056
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Chapter 6 Computer Programmingodp

Chapter Six of the document covers pointers in C++, including their declaration, initialization, and arithmetic. It explains how pointers relate to arrays, pointers to pointers, and pointers to functions, along with dynamic memory management. Key concepts include the use of the address operator (&), dereference operator (*), and the implications of pointer arithmetic.

Uploaded by

birhanua056
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 51

Computer Programming

[ECEg-1052]

Chapter Six:
Pointers

Prepared by Electronics and Computer Engineering Chair


Outline
 Declaring variables of type pointer
 Pointers and Arrays
 Pointer initialization
 Arithmetic of pointers
 Pointers to pointers
 Pointers to functions
 Dynamic memory
6.1 Declaring variables of type pointer
 A pointer is a variable that holds a memory address, usually the
location of another variable in a memory.

Address (dereference) operator (&)


 It is used as a variable prefix to know where the variable is stored and can
be translated as "address of", thus: &variable1 can be read as "address of
variable1".
For example:
ted = &andy;
would assign to variable ted the address of variable andy
3
Cont’d...
 Suppose that andy has been placed in the memory address 1776 and that
we write the following:
The result is shown in the following diagram:
andy = 25;
fred = andy;
ted = &andy;

A variable storing a memory address is called a pointer (like ted in the


previous example) as it points to a specific memory location whose address it
is storing under its name.
4
Cont’d...
Reference operator (*)
 To access the value stored in the variable pointed by pointer just by
preceding the pointer identifier with the reference operator asterisk(*),
that can be literally translated to "value pointed by".
* mypointer can be read as "value pointed by mypointer".
 Therefore, following with the values of the previous example, if we write:
beth = *ted;
 Read as: "beth equal to value pointed by ted"
 beth would take the value 25, since ted is 1776, and the value pointed by
1776 is 25.
5
Cont’d...


Notice the difference of including or not including the reference asterisk :
beth = ted; // beth equal to ted ( 1776 )
beth = *ted; // beth equal to value pointed by ted ( 25 )

6
Cont’d...
 At this point, and following with the same example initiated above where:
andy = 25;
ted = &andy;
you should be able to clearly see that all the following expressions are true:
andy == 25
&andy == 1776
ted == 1776
*ted == 25
7
Cont’d...
 The general form of a pointer declaration is:
type * pointer_name;
 where type is the type of data pointed, not the type of the pointer itself.
For example:
int * a; //creates integer pointer a
char * b; // creates a character pointer b
float * c; // creates a float pointer c

Multiple pointers require multiple asterisks
int *myPtr1, *myPtr2;
8
Cont’d...
 Two special operators * and & are used with pointers.
 The & returns the memory address of its operand (usually a variable).
 The & is used to in initialize a pointer to point to a variables address.
Example:
int i=25 ; // declares an int variable i
int * a ; // declares an int pointer a
a= & i ; // initialises a; stores the memory address of i into a

9
Cont’d...
 The pointer operator, *, does the reverse of &.
 The unary operator * returns the value of the variable located at the address
following it.
Example: Suppose address of i is 1776
Output:
int i =80;
7
int j; 80
int * a; 1776
a=&i;
j =* a ; // the value (80) stored in the address it points to
* a=7 ; // puts 7 at address (&i) pointed by a
cout << i<<endl;
cout << j<<endl;
cout << a <<endl; 10
Cont’d...

#include <iostream>
Output:
using namespace std;
Value1==10
// my first pointer
int main (){ value2==20
int value1 = 5, value2 = 15;
int * mypointer;
mypointer = &value1;
*mypointer = 10;
mypointer = &value2;
*mypointer = 20;
cout << "value1==" << value1 << endl;
cout<<"value2==" << value2;
} 11
Cont’d...
//Here is an example a bit more complicated:
#include <iostream> Output:
using namespace std;
int main (){ Value1==10
int value1 = 5, value2 = 15; value2==20
int *p1, *p2; // more pointers
p1 = &value1; // p1 = address of value1
p2 = &value2; // p2 = address of value2
*p1 = 10; // value pointed by p1 = 10
*p2 = *p1; // value pointed by p2 = value pointed by p1
p1 = p2; // p1 = p2 (v alue of pointer copied)
*p1 = 20; // value pointed by p1 = 20
cout << "value1==" << value1 << endl;
cout<<" value2==" << value2;
} 12
6.2 Pointers and Arrays

C++ interprets the name of an array as a pointer pointing to the first
element of the array.

For example, supposing these two declarations:
int numbers [20];
int * p;
the following allocation would be valid:
p = numbers;

13
Cont’d...
 The only difference is that we could assign another value to the pointer p
whereas numbers will always point to the first of the 20 integer numbers of
type int with which it was defined.
 So, unlike p, that is an ordinary variable pointer, numbers is a constant pointer
(indeed an array name is a constant pointer).
 Therefore, although the previous expression was valid, the following allocation
is not:
numbers = p;
 because numbers is an array (constant pointer), and no values can be
assigned to constant identifiers.

14
Cont’d...
 Due to the character of variables all the expressions that include pointers in the following example are perfectly valid:
#include <iostream>
using namespace std;
int main (){
int numbers[5]; Output:
int * p;
10, 20, 30, 40, 50,
p = numbers;
*p = 10;
p++;
*p = 20;
p = &numbers[2];
*p = 30;
p = numbers + 3;
*p = 40;
p = numbers;
*(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
}
15
Cont’d...
 Since name of an array (array name) is a pointer to its first element, the array
name +1 gives the address of the second element of the array, array name +2
gives the address of the third element and so forth.
 For example, both following expressions:
a[5] = 0; // a [offset of 5] = 0
*(a+5) = 0; // pointed by (a+5) = 0

are equivalent and valid either if a is a pointer or if it is an array.

16
6.3 Pointer initialization
 When declaring pointers we may want to explicitly specify to which
variable we want them to point,
int number;
int *tommy = &number;
this is equivalent to:
int number;
int *tommy;
tommy = &number;
17
Cont’d….
 You must consider that at the moment of declaring a pointer, the asterisk
(*) indicates only that it is a pointer, it in no case indicates the reference
operator (*).
 Remember, they are two different operators, although they are written with
the same sign.
 Thus, we must take care not to confuse the previous with:
int number;
int *tommy;
*tommy = &number;
that anyway would not have much sense in this case.

18
Cont’d...
 As in the case of arrays, the compiler allows the special case that we want
to initialize the content at which the pointer points with constants at the
same moment as declaring the variable pointer:
char * terry = "hello";
 In this case static storage is reserved for containing "hello" and a pointer
to the first char of this memory block (that corresponds to 'h') is assigned to
terry.

19
Cont’d...
 If we imagine that "hello" is stored at addresses 1702 and following, the
previous declaration could be outlined thus:

 It is important to indicate that terry contains the value 1702 and not 'h' nor
"hello", although 1702 points to these characters.

20
Cont’d...
 The pointer terry points to a string of characters and can be used exactly as
if it was an Array (remember that an array is just a constant pointer).
 For example, if our temper changed and we wanted to replace the 'o' by a
'!' sign in the content pointed by terry, we could do it by any of the
following two ways:
terry[4] = '!';
*(terry+4) = '!';

21
6.4 Arithmetic of pointers

Only addition and subtraction operations are allowed to be conducted.

When we saw the different data types that exist, we saw that some occupy
more or less space than others in the memory.

For example, in the case of integer numbers, char occupies 1 byte, short
occupies 2 bytes and long occupies 4.

Let's suppose that we have 3 pointers:
char *mychar;
short *myshort;
long *mylong;

22
Cont’d...

They point to memory locations 1000, 2000 and 3000 respectively.
So if we write:
mychar++;
myshort++;
mylong++;
 mychar, as you may expect, would contain the value 1001. Nevertheless,
myshort would contain the value 2002, and mylong would contain 3004.
 The reason is that when adding 1 to a pointer we are making it to point to
the following element of the same type with which it has been defined, and
therefore the size in bytes of the type pointed is added to the pointer.

23
Cont’d...

 This is applicable both when adding and subtracting any number to a


pointer. It would happen exactly the same if we write:
mychar = mychar + 1;
myshort = myshort + 1;
mylong = mylong + 1; 24
Cont’d...

It is important to warn you that both increase (++) and decrease (--)
operators have a greater priority than the reference operator asterisk
(*), therefore the following expressions may lead to confusion:
*p++;
*p++ = *q++;

The first one is equivalent to *(p++) and what it does is to increase p (the
address where it points to - not the value that contains).

25
Cont’d...

In the second, because both increase operators (++) are after the
expressions to be evaluated and not before, first the value of *q is assigned
to *p and then both q and p are increased by one. It is equivalent to:
*p = *q;
p++;
q++;

Like always, I recommend you use parenthesis () in order to avoid
unexpected results.

26
6.5 Pointers to pointers
 C++ allows the use of pointers that point to pointers, that these, in its turn,
point to data. In order to do that we only need to add an asterisk (*) for
each level of reference:
char a; 
Supposing the randomly chosen memory locations
of 7230, 8092 and 10502:
char * b;
char ** c;
a = 'z';
b = &a; 
c is a variable of type (char **) with a value of 8092
c = &b;

*c is a variable of type (char*) with a value of 7230

**c is a variable of type (char) with a value of 'z' 27
Cont’d...
void pointers
 The type of pointer void is a special type of pointer.
 Void pointers can point to any data type, from an integer value or a float
to a string of characters.
 Its sole limitation is that the pointed data cannot be referenced directly
(we can not use reference asterisk * operator on them), since its length is
always undetermined, and

For that reason we will always have to resort to type casting or

Assignations to turn our void pointer to a pointer of a concrete data
type to which we can refer.
28
Cont’d...
#include <iostream>
Output:
using namespace std;
int main (){ 9, 40
int b = 9;
float c = 12.4;
float* d;
void* e;
d=&c;
*d=40;
e=&b;
cout << (*((int*)e)) << ","<<c;
}
29
6.6 Pointers to functions
 C++ allows operations with pointers to functions.
 In order to declare a pointer to a function we must declare it like the
prototype of the function except the name of the function is enclosed
between parenthesis () and a pointer asterisk (*) is inserted before the
name.
 It might not be a very handsome syntax, but that is how it is done in C++.
Example
void centimize(double* ptrd)

30
Cont’d...
// arguments passed by pointer
Output:
#include <iostream>
using namespace std; Var = 10.0 inches
void centimize(double* ptrd){ Var = 25.4 centimeters
*ptrd *= 2.54; //*ptrd is the same as var
}
int main(){
double var = 10.0; //var has value of 10 inches
cout << "var = " << var << " inches" << endl;
centimize(&var); //change var to centimeters
cout << "var = " << var << " centimeters" << endl;
return 0;
} 31
Cont’d...
 The function centimize() is declared as taking an argument that is a pointer
to double :

void centimize(double*) // argument is pointer to double
 When main() calls the function, it supplies the address of the variable as
the argument:

centimize(&var);
 Remember that this is not the variable itself, as it is in passing by reference,
but the variable’s address.

32
Cont’d...
 Because the centimize() function is passed an address, it must use the
dereference operator,

*ptrd , to access the value stored at this address:

*ptrd *= 2.54; // multiply the contents of ptrd by 2.54 of course this is
the same as *ptrd = *ptrd * 2.54; // multiply the contents of ptrd by 2.54
where the standalone asterisk means multiplication.
 Passing a pointer as an argument to a function is in some ways similar to
passing a reference.

They both permit the variable in the calling program to be modified by
the function.
33
6.7 Dynamic memory
■ Until now, in our programs, we have only had as much memory as we have
requested in declarations of variables, arrays and other objects that we
included, having the size of all of them fixed before the execution of the
program.
■ But, what if we need a variable amount of memory that can only be
determined during the program execution (runtime), for example, in case
that we need an user input to determine the necessary amount of space?
■ The answer is dynamic memory, for which C++ integrates the operators
new and delete.

34
Cont’d...
Operators new and new[ ]

In order to request dynamic memory, the operator new exists.

new is followed by a data type and optionally the number of elements
required within brackets [].

It returns a pointer to the beginning of the new block of assigned memory.
Its form is:
pointer = new type
or
pointer = new type [elements]

The first expression is used to assign memory to contain one single element
of type.

The second one is used to assign a block (an array) of elements of type. 35
Cont’d...
For example:
int * bobby;
bobby = new int [5];

In this case, the operating system has assigned space for 5 elements of type int in
a heap and it has returned a pointer to its beginning that has been assigned to
bobby.

Therefore, now, bobby points to a valid block of memory with space for 5 int
elements.

36
Cont’d...
 You could ask what is the difference between declaring a normal array and assigning
memory to a pointer as we have just done.

 The most important one is that the size of an array must be a constant value, which
limits its size to what we decide at the moment of designing the program before its
execution, whereas the dynamic memory allocation allows assigning memory during
the execution of the program using any variable, constant or combination of both as
size.

37
Cont’d...

The dynamic memory is generally managed by the operating system, and in multitask
interfaces it can be shared between several applications, so there is a possibility that the
memory exhausts.

If this happens and the operating system cannot assign the memory that we request with
the operator new, a null pointer will be returned.

For that reason it is recommended to always check to see if the returned pointer is null
after a call to new.
int * bobby;
bobby = new int [5];
if (bobby == NULL) {
// error assigning memory. Take measures.
};
38
Cont’d...
Operator delete

Since the necessity of dynamic memory is usually limited to concrete
moments within a program, once it is no longer needed it should be freed
so that it becomes available for future requests of dynamic memory.

The operator delete exists for this purpose, whose form is:
delete pointer;
or
delete [] pointer;

The first expression: to delete memory allocated for a single element, and

The second one for memory allocated for multiple elements (arrays). 39
Cont’d...
#include <iostream> // introduces operator new
#include <cstring>
using namespace std;
int main(){
char* str = "Idle hands are the devil’s workshop.";
int len = strlen(str); //get length of str
char* ptr; //make a pointer to char
ptr = new char[len+1]; //set aside memory: string + ‘\0’
strcpy(ptr, str); //copy str to new memory area ptr
cout << "ptr=" << ptr << endl; //show that ptr is now in str
delete[] ptr; //release ptr’s memory
return 0;
Output:
}
Ptr= Idle hands are the devil’s workshop.
40
Cont’d...

NULL is a constant value defined in many fold C++ libraries specially designed
to indicate null pointers.

In case that this constant is not defined you can do it yourself by defining it to 0:

#define NULL 0

It is indifferent to put 0 or NULL when checking pointers, but the use of NULL
with pointers is widely extended and it is recommended for greater legibility.

The reason is that a pointer is rarely compared or set directly to a numerical
literal constant except precisely number 0, and this way this action is
symbolically masked.

41
Cont’d...

Dynamic memory in ANSI-C



Operators new and delete are exclusive of C++ and they are not available
in C language.

In C language, in order to assign dynamic memory we have to resort to the
library stdlib.h.

We are going to see them, since they are also valid in C++ and they are
used in some existing programs.

42
Cont’d...
The function malloc
 It is the generic function to assign dynamic memory to pointers.
 Its prototype is:
void * malloc (size_t nbytes);
where

nbytes is the number of bytes that we want to be assigned to the
pointer.

The type size_t is defined in stdlib.h as, more or less, an unsigned
integer.
 The function returns a pointer of type void*, which is the reason why we
have to type cast the value to the type of the destination pointer. 43
Cont’d...
Example:
char * ronny;
ronny = (char *) malloc (10);

This assigns to ronny a pointer to an usable block of 10 bytes.

When we want to assign a block of data of a different type other than char
(different from 1 byte) we must multiply the number of elements desired by
the size of each element.

44
Cont’d...

Luckily we have at our disposition the operator sizeof, that returns the size
of the type of a concrete datum.
int * bobby;
bobby = (int *) malloc (5 * sizeof(int));

This piece of code assigns to bobby a pointer to a block of 5 integers of
type int, this size can be equal to 2, 4 or more bytes according to the system
where the program is compiled.

45
Cont’d...
The function calloc

calloc is very similar to malloc in its operation, its main difference is in its
prototype:
void * calloc (size_t nelements, size_t size);

since it admits 2 parameters instead of one.

These two parameters are multiplied to obtain the total size of the memory
block to be assigned.

Usually the first parameter (nelements) is the number of elements and the
second one (size) serves to specify the size of each element.

46
Cont’d...

For example, we could define bobby with calloc thus:
int * bobby;
bobby = (int *) calloc (5, sizeof(int));

Another difference between malloc and calloc is that calloc initializes all
its elements to 0.

47
Cont’d...
The function realloc

It changes the size of a block of memory already assigned to a pointer.
void * realloc (void * pointer, size_t size);

Pointer parameter receives a pointer to an already assigned memory block
or a null pointer, and size specifies the new size that the memory block
shall have.

The function assigns size bytes of memory to the pointer.

48
Cont’d...

The function may need to change the location of the memory block so that
the new size can fit, in that case the present content of the block is copied
to the new one to guarantee that the existing data is not lost.

The new pointer is returned by the function.

If it has not been possible to assign the memory block with the new size it
returns a null pointer but the pointer specified as parameter and its content
remains unchanged.

49
Cont’d...
The function free

It releases a block of dynamic memory previously assigned using malloc,
calloc or realloc.
void free (void * pointer);

This function must only be used to release memory assigned with functions
malloc, calloc and realloc.

50
Thank You !

51

You might also like