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

Chapter - Pointers

Uploaded by

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

Chapter - Pointers

Uploaded by

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

ECEG-: INTRODUCTION TO COMPUTING

POINTERS

Tsigabu T.
Lecturer
Computer Engineering chair
School of Electrical and Computer Engineering
Ethiopian Institute of Technology- Mekelle (EiT-M)
Mekelle
1 University,
Mekelle, Ethiopia
Lecture #1
INTRODUCTION
 When you declare a variable, the computer associates the variable
name with a particular location in memory and stores a value there.
 When you refer to the variable by name in your code, the
computer must take two steps:
1. Look up the address that the variable name corresponds to
2. Go to that location in memory and retrieve or set the value it contains
 C++ allows us to perform either one of these steps independently
on a variable with the & and * operators:
 1. &x evaluates to the address of x in memory.
 2. *( &x ) takes the address of x and dereferences it – it
retrieves the value at that location in memory. *( &x ) thus
evaluates to the same thing as x.
 Pointers are an important feature of C++ (and C), while many other
languages, such as Visual Basic and Java, have no pointers at all.2

 In some situations pointers provide an essential tool for increasing


the power of C++.
WHAT ARE POINTERS FOR (WHY USE POINTER)?
Here are some common uses:
• Accessing array elements
• Passing arguments to a function when the function
needs to modify the original argument
• Passing arrays and strings to functions
•A notable example is the creation of data structures such
as linked lists and binary trees.
 Working with memory locations that regular variables
don’t give you access to
 Several key features of C++, such as virtual functions,
the new operator, and the this pointer require the
use of pointers.
 Working with strings and arrays
 Creating new variables in memory while the program is
running 3
 Creating arbitrarily-sized lists of values in memory
ADDRESSES AND POINTERS
 Every byte in the computer’s memory has an address.
 Addresses are numbers, just as they are for
houses on a street.
 The numbers start at 0 and go up from there—1,
2, 3, and so on. If you have 1MB of memory, the
highest address is 1,048,575. (Of course you have
much more.)
 Your program, when it is loaded into memory,
occupies a certain range of these addresses.
 That means that every variable and every
function in your program starts at a particular
address. 4

 The following Figure shows how this looks.


MEMORY AND PROGRAMS

5
What Are Pointers?

 A pointer is a variable that contains a memory address.


 Very often this address is the location of another variable.
 For example, if x contains the address of y, then x is said
to "point to" y.
 Pointer variables must be declared as such. The general
form of a pointer variable declaration is
type *var-name;
 Here, type is the pointer’s base type; it must be a valid
C++ type.
 var-name is the name of the pointer variable.
 For example, to declare p to be a pointer to an integer, use
this declaration: int *p; For a float pointer, use float *p;
 int *ip; // pointer to integers
6
 double *dp; // pointer to doubles
POINTER VARIABLES
 We’ve seen variable types that store characters, integers,
floating-point numbers, and so on. When we declare a variable
some memory is allocated for it. The memory location can be
referenced through the identifier “i”. Thus, we have two
properties for any variable : its address and its data value.
 Addresses are stored similarly.
 A variable that holds an address value is called a pointer
variable, or simply a pointer.
 With pointer variables you can indirectly manipulate data stored
in other variables.
 Your pointer variables must always point to the correct
type of data. For example, when you declare a pointer to
be of type int, the compiler assumes that anything it
points to will be an integer value.
For example, the following fragment is incorrect:
int *p;
double f;
// ... 7

p = &f; // ERROR
#include <iostream>
using namespace std;
int main()
{ int var1 = 11; //two integer variables
int var2 = 22;
cout << &var1 << endl //print addresses of variables
<< &var2 << endl << endl;
int* ptr; //pointer to integers
ptr = &var1; //pointer points to var1
cout << ptr << endl; //print pointer value
ptr = &var2; //pointer points to var2
cout << ptr << endl; //print pointer value 8

return 0; }
IN THIS PROGRAM
 It defines two integer variables, var1 and var2, and
initializes them to the values 11 and 22.
 It then prints out their addresses.

 The program next defines a pointer variable in the


line int* ptr;
 The syntax used in C++ allows pointers to any
type to be declared:
char* cptr; // pointer to char
int* iptr; // pointer to int
float* fptr; // pointer to float
Student* distptr; // pointer to user-defined student struct

9
The Pointer Operators
 There are two special operators that are used with pointers: *
and &.
1. The Address-of Operator &
 You can find the address occupied by a variable by using the address-
of operator &
 It is a unary operator that returns the memory address of its
operand. (Recall that a unary operator requires only one
operand.)
 For example, balptr = &balance; puts into balptr the memory
address of the variable balance.
 This address is the location of the variable in the computer’s
internal memory. It has nothing to do with the value of balance.
 The operation of & can be remembered as returning "the
address of" the variable it precedes. Therefore, the above
assignment statement could be verbalized as "balptr receives
the address of balance.“
10
 assume that the variable balance is located at address 100.
Then, after the assignment takes place, balptr has the value
100.
THE ADDRESS-OF OPERATOR &- EXAMPLE
#include <iostream>
using namespace std;
int main()
{
int var1 = 11; //define and initialize
int var2 = 22; //three variables
int var3 = 33;
cout << &var1 << endl //print the addresses
<< &var2 << endl //of these variables
<< &var3 << endl;
return 0;
}
This simple program defines three integer variables and initializes them to the
values 11, 22, and 33. It then prints out the addresses of these variables. 11
2. The "at address or dereference" operator (*) - value
pointed to by
 It is the complement of &.

 It is a unary operator that returns the value of the


variable located at the address specified by its operand.
 Continuing with the same example, if balptr contains the
memory address of the variable balance, then value =
*balptr; will place the value of balance into value.
 For example, if balance originally had the value 3,200,
then value will have the value 3,200, because that is the
value stored at location 100, the memory address that
was assigned to balptr.
 The operation of * can be remembered as "at address."
In this case, then, the statement could be read as "value
receives the value at address balptr."
12
13
The following program executes the sequence of
operations shown in Figure above:
#include <iostream>
using namespace std;
int main()
{
int balance;
int *balptr;
int value;
balance = 3200;
balptr = &balance;
value = *balptr;
cout << "balance is: " << value << '\n';
return 0;
} 14
ECEG-: INTRODUCTION TO COMPUTING
POINTERS

Tsigabu T.
Lecturer
Computer Engineering chair
School of Electrical and Computer Engineering
Ethiopian Institute of Technology- Mekelle (EiT-M)
Mekelle
15 University,
Mekelle, Ethiopia
Lecture #2
ASSIGNING VALUES THROUGH A POINTER

 Assuming that p is an integer pointer, this assigns


the value 101 to the location pointed to by p:
*p = 101; That is, "at the location pointed to by
p, assign the value 101."
 To increment or decrement the value at the
location pointed to by a pointer, you can use a
statement like this:
(*p)++; The parentheses are necessary because the
* operator has lower precedence than the ++
operator.
 The following program demonstrates assignment
using a pointer. 16
// more pointers
#include <iostream>
using namespace std;

int main ()
{
int numbers[5];
int * p;
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] << ", ";
return 0;
}
The following program demonstrates assignment
using a pointer.
#include <iostream>
using namespace std;
int main()
{
int *p, num;
p = &num;
*p = 100;
cout << num << ' ';
(*p)++;
cout << num << ' ';
(*p)--;
cout << num << '\n';
return 0; 18
}
EXAMPLE
// This program demonstrates the use of the indirection
// operator.
#include <iostream.h>

void main(void)
{
int x = 25;
int *ptr;

ptr = &x; // Store the address of x in ptr


cout << "Here is the value in x, printed twice:\n";
cout << x << " " << *ptr << endl;
*ptr = 100;
cout << "Once again, here is the value in x:\n";
cout << x << " " << *ptr << endl;
19
}
#include <iostream>
using namespace std;
int main()
{
int x = 25, y = 50, z = 75;
int *ptr;
cout << "Here are the values of x, y, and
z:\n";
cout << x << " " << y << " " << z << endl;
ptr = &x; // Store the address of x in ptr
*ptr *= 2; // Multiply value in x by 2
ptr = &y; // Store the address of y in ptr
*ptr *= 2; // Multiply value in y by 2
ptr = &z; // Store the address of z in ptr
*ptr *= 2; // Multiply value in z by 2
cout << "Once again, here are the values of
x, y, and z:\n";
cout << x << " " << y << " " << z << endl;
return o; 20

}
POINTER ARITHMETIC
 Some mathematical operations may be performed on
pointers.
 The ++ and -- operators may be used to increment or decrement
a pointer variable.
 An integer may be added to or subtracted from a pointer
variable. This may be performed with the +, - +=, or -=
operators.
 A pointer may be subtracted from another pointer.
 There are only four arithmetic operators that can be used
on pointers: ++, – –, +, and –.
 To understand what occurs in pointer arithmetic, let p1 be
an integer pointer with a current value of 2,000 (that is, it
contains the address 2,000). Assuming 32-bit integers,
 after the expression p1++; the contents of p1 will be 2,004,
not 2,001! Each time p1 is incremented, it will point to the
next integer.
 The same is true of decrements. For example, p1--; will
cause p1 to have the value 1,996, assuming that it 21
previously was 2,000.
 You are not limited to only increment and decrement operations. You can also add or
subtract integers to or from pointers.
 The expression p1 = p1 + 9; makes p1 point to the ninth element of p1’s base
type, beyond the one to which it is currently pointing.
 While you cannot add pointers, you can subtract one pointer from another (provided
they are both of the same base type). The remainder will be the number of elements of the
base type that separate the two pointers.
 Other than addition and subtraction of a pointer and an integer, or the subtraction of two
pointers, no other arithmetic operations can be performed on pointers. For example, you
cannot add or subtract float or double values to or from pointers.

When fundamental data types were introduced, we saw that types have different sizes.
For example: char always has a size of 1 byte, bool is one byte, and int two bytes and float
are even larger (four bytes); the exact size of these being dependent on the system.
 For example, let's imagine that in a given system, char takes 1 byte, short takes 2 bytes,
and long takes 4.

Suppose now that we define three pointers in this compiler:
char *mychar;
short *myshort;
long *mylong;
 and that we know that they point to the memory locations 1000, 2000, and 3000,
respectively.

Therefore, if we write:
++mychar;
++myshort;
++mylong; 22
// This program uses a pointer to display the
contents
// of an integer array.
#include <iostream.h>

void main(void)
{
int set[8] = {5, 10, 15, 20, 25, 30, 35, 40};
int *nums, index;
nums = set;
cout << "The numbers in set are:\n";
for (index = 0; index < 8; index++)
{
cout << *nums << " ";
nums++;
}
cout << "\nThe numbers in set backwards are:\n";
for (index = 0; index < 8; index++)
{
nums--;
cout << *nums << " ";
}
} 24
EXAMPLE
// Demonstrate pointer arithmetic.
#include <iostream>
using namespace std;
int main()
{
int *i, j[10];
double *f, g[10];
int x;
i = j;
f = g;
for(x=0; x<10; x++)
cout << i+x << ' ' << f+x << '\n';
return 0; 25
}
POINTER INITIALIZATION

Pointers can be initialized to point to specific locations
at the very moment they are defined:
int myvar;
int * myptr = &myvar;

Pointers can be initialized either to the address of a
variable (such as in the case above), or to the value of
another pointer (or array):
int myvar;
int *foo = &myvar;
int *bar = foo;
VOID POINTERS
 The void type of pointer is a special type of pointer. In C++,
void represents the absence of type.
 Therefore, void pointers are pointers that point to a value
that has no type (and thus also an undetermined length
and undetermined dereferencing properties).
 This gives void pointers a great flexibility, by being able to
point to any data type, from an integer value or a float to a
string of characters.
 In exchange, they have a great limitation: the data pointed
by them cannot be directly dereferenced (which is logical,
since we have no type to dereference to), and for that
reason, any address in a void pointer needs to be
transformed into some other pointer type that points to a
concrete data type before being dereferenced.
// ptrvoid.cpp
// pointers to type void
#include <iostream>
using namespace std;
int main()
{
int intvar; //integer variable
float flovar; //float variable
int* ptrint; //define pointer to int
float* ptrflo; //define pointer to float
void* ptrvoid; //define pointer to void
ptrint = &intvar; //ok, int* to int*
// ptrint = &flovar; //error, float* to int*
// ptrflo = &intvar; //error, int* to float*
ptrflo = &flovar; //ok, float* to float*
ptrvoid = &intvar; //ok, int* to void*
ptrvoid = &flovar; //ok, float* to void*
return 0;
28
}
POINTERS AND ARRAYS
 The name of an array is actually a pointer to the first
element in the array. Writing myArray[3] tells the compiler
to return the element that is 3 away from the starting
element of myArray.
 To begin, consider this fragment:
char str[80];
char *p1;
p1 = str;
 Here, str is an array of 80 characters and p1 is a character pointer.
 Thus the assignment p1 = str assigns the address of str[0] to p1.
 When an unindexed array name is used in an expression, it yields
a pointer to the first element in the array.
#include <iostream>
Using namespace std;
int main()
{
short numbers[] = {10, 20, 30, 40, 50};
29
cout << "The first element of the array is ";
cout << *numbers << endl;
}

For example, consider these two declarations:
int myarray [20];
int * mypointer;
The following assignment operation would be valid:
mypointer = myarray;
But, the following assignment would not be valid:
myarray = mypointer;

The main difference being that mypointer can be
assigned a different address, whereas myarray can never
be assigned anything, and will always represent the
same block of 20 elements of type int.
 For example, if you want to access the fifth element in
str, you could use: str[4] or *(p1+4)
 In effect, C++ allows two methods of accessing array
elements: pointer arithmetic and array indexing.
This is important because pointer arithmetic can
sometimes be faster than array indexing 30
POINTER CONSTANTS AND POINTER VARIABLES
I. POINTER CONSTANTS

#include <iostream>
using namespace std;
int main()
{ //array
int intarray[5] = { 31, 54, 77, 52, 93 };
for(int j=0; j<5; j++) //for each element,
cout << *(intarray+j) << endl; //print value
return 0;
}
Could you write *(intarray++)?
Ans: No, because it is pointer Constant. 31
II. POINTER VARIABLE
#include <iostream>
using namespace std;
int main()
{
int intarray[] = { 31, 54, 77, 52, 93 }; //array
int* ptrint; //pointer to int
ptrint = intarray; //points to intarray
for(int j=0; j<5; j++) //for each element,
cout << *(ptrint++) << endl; //print value
return 0;
}
But, because ptrint is a variable and not a constant, it 32
can be incremented.
EXAMPLE
// This program processes the contents of an array.
// Pointer notation is used.
#include <iostream.h>

void main(void)
{
int numbers[5];

cout << "Enter five numbers: ";


for (int count = 0; count < 5; count++)
cin >> *(numbers + count);
cout << "Here are the numbers you entered:\n";
for (int count = 0; count < 5; count++)
cout << *(numbers + count)<< " ";
cout << endl;
33
}
POINTERS TO POINTERS

C++ allows the use of pointers that point to pointers, that these,
in its turn, point to data (or even to other pointers).

The syntax simply requires an asterisk (*) for each level of
indirection in the declaration of the pointer:

char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;
 This, assuming the randomly chosen memory locations for each
variable of 7230, 8092, and 10502, could be represented as:

The new thing in this example is variable c,
which is a pointer to a pointer, and can be used in
three different levels of indirection, each one of
them would correspond to a different value:
c is of type char** and a value of 8092
*c is of type char* and a value of 7230
**c is of type char and a value of 'z'
ECEG-: INTRODUCTION TO COMPUTING
POINTERS

Tsigabu T.
Lecturer
Computer Engineering chair
School of Electrical and Computer Engineering
Ethiopian Institute of Technology- Mekelle (EiT-M)
Mekelle
36 University,
Mekelle, Ethiopia
Lecture #3
DYNAMIC MEMORY
 In the programs seen in previous chapters, all memory
needs were determined before program execution by
defining the variables needed.
 But there may be cases where the memory needs of a
program can only be determined during runtime. For
example, when the memory needed depends on user
input. That is, Variables may be created and destroyed
while a program is running.
 On these cases, programs need to dynamically allocate
memory, for which the C++ language integrates the
operators new and delete.
 That is,Use the new operator to dynamically allocate
memory, and Use delete to dynamically deallocate
memory.
OPERATORS NEW AND NEW[]

This versatile operator obtains memory from the operating system and
returns a pointer to its starting point. Dynamic memory is allocated
using operator new.
 new is followed by a data type specifier and, if a sequence of
more than one element is required, the number of these within
brackets [].

Its syntax is:
pointer = new type
pointer = new type [number_of_elements]

The first expression is used to allocate memory to contain one single
element of type type. The second one is used to allocate a block (an
array) of elements of type type, where number_of_elements is an
integer value representing the amount of these.

For example:
int * foo;
foo = new int [5];
 In this case, the system dynamically allocates space for five elements of
type int and returns a pointer to the first element of the sequence,
which is assigned to foo (a pointer). Therefore, foo now points to a valid
block of memory with space for five elements of type int.
#include <iostream>
#include <cstring> //for strlen
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;
}
OPERATORS DELETE AND DELETE[]

In most cases, memory allocated dynamically is only needed during
specific periods of time within a program; once it is no longer
needed, it can be freed so that the memory becomes available again
for other requests of dynamic memory.

To ensure safe and efficient use of memory, the new operator is
matched by a corresponding delete operator that returns memory to
the operating system.

This is the purpose of operator delete, whose syntax is:
delete pointer;
delete[] pointer;

the statement delete[] ptr; returns to the system whatever
memory was pointed to by ptr.

The first statement releases the memory of a single element
allocated using new, and the second one releases the memory
allocated for arrays of elements using new and a size in brackets
([]).

The value passed as argument to delete shall be either a pointer to
a memory block previously allocated with new, or a null pointer (in
the case of a null pointer, delete produces no effect).
#include <iostream>
using namespace std;
int main()
{
float *sales, total = 0, average;
int numDays;

cout << "How many days of sales figures do you wish to process?";
cin >> numDays;
sales = new float[numDays]; // Allocate memory
if (sales == NULL) // Test for null pointer
{
cout << "Error allocating memory!\n";
return 1;
} // Get the sales figures from the user
cout << "Enter the sales figures below.\n";
for (int count = 0; count < numDays; count++)
{
cout << "Day " << (count + 1) << ": ";
cin >> sales[count];
} // Calculate the total sales
for (int count = 0; count < numDays; count++)
{
total += sales[count];
}
cout << "\n\nTotal sales: $" << total << endl;
average = total/numDays;
cout << "average sales: $" << average << endl;
delete [] sales; // Free dynamically allocated memory
return 0; 42
}
THE END

43

You might also like