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

Pointers and Memory Allocation

The document discusses pointers and dynamic memory allocation in C/C++. It explains what pointers are, how to declare and initialize pointers, and how to dereference pointers using the asterisk operator. It also covers passing parameters by value versus by reference and how arrays are related to pointers.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views

Pointers and Memory Allocation

The document discusses pointers and dynamic memory allocation in C/C++. It explains what pointers are, how to declare and initialize pointers, and how to dereference pointers using the asterisk operator. It also covers passing parameters by value versus by reference and how arrays are related to pointers.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 46

Pointers & Dynamic Memory

Allocation
CSE225: Data Structures and Algorithms
What is a Pointer?
• Variables allow the programmer to directly manipulate the data in
memory.
• A pointer variable, however, does not store a value but store the
address of the memory space which contains the value i.e. it directly
points to a specific memory address.
• Why would we want to use pointers?
• To call a function with memory addresses as parameters so that it can change values
of variables created outside the function.
• To create a dynamic data structure which can grow larger or smaller as necessary.
Pointers
• A pointer is a variable that contains the address
of another variable.
address content
• We say that a pointer points/references 0x00000000

another variable. 0x00000001


.
.
.
letter 0x180A96e8 65
ptr letter
0x180A96e9
0x180A96e8 65 ptr 0x180A96f0
0x180A96f0 0x180A96e8 0x180A96f1
0x180A96e8
The variable ptr contains the 0x180A96f2

address of letter 0x180A96f3


.
.
Pointer Declaration
• General Format:
data_type *pointer_name;

• A pointer declaration such as,


int *numberPtr;
• declares numberPtr as a variable that points to an integer variable. Its content is a
memory address.

• The * indicates that the variable being declared is a pointer variable


instead of a normal variable.
Pointer Declaration
• Consider the following declaration
int *numberPtr, number = 20;
• In this case, two memory address have been reserved, associated
with the names numberPtr and number.
• The value in variable number is of type integer, and the value in
variable numberPtr is an address for another memory location.

numberPtr number

? 20
130 144
Pointer Initialization
•To prevent the pointer from pointing to a random memory address,
it is advisable that the pointer is initialized to NULL (the value 0) or
an address before being used.

•A pointer with the value NULL, points to nothing.

•Initializing a pointer to 0 is equivalent to initializing a pointer to


NULL, but NULL is preferred.
int *numberPtr = NULL, number = 20;
numberPtr number

0 20
130 144
Pointer Operator (& and *)
• When a pointer is created, it does not point to any valid memory
address. Therefore, we need to assign a variable’s address to it
• using the & operator (referencing operator/ address-of operator).
• Look at this example:
int *numberPtr, number = 20;
numberPtr = NULL;
numberPtr number

0 20
130 144
Pointer Operator (& and *)
• When a pointer is created, it does not point to any valid memory address.
Therefore, we need to assign a variable’s address to it
• using the & operator (referencing operator/ address-of operator).
• Look at this example:
int *numberPtr, number = 20;
numberPtr = NULL;
numberPtr = &number;
• The statement numberPtr = &number assigns the address of the variable
number to a pointer variable numberPtr. Variable numberPtr is then said as
to “point to” variable number.
numberPtr number

144 20
130 144
Pointer Operator (& and *)
•After a pointer is assigned a particular address, the value at the pointed address
can be accessed/modified
• using the * operator (dereferencing operator/ value-at operator).
•Look at this example:
int *numberPtr, number = 20;
numberPtr = NULL;
numberPtr = &number;
*numberPtr = 16;
•The statement *numberPtr = 16 changes the content at the address 144 (i.e.
value of variable number) from 20 to 16.
numberPtr number

144 16
130 144
Function Call by Value
#include <iostream>
using namespace std;
void swap(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
} Local variables (get destroyed
int main(void) after function ends, no effect on
{ x and y inside main)
int x = 5, y = 10;
cout << "Before swap function: "; Output:
cout << "x = " << x << ", y = " << y << endl; Before swap function: x = 5, y = 10
swap(x,y); After swap function: x = 5, y = 10
cout << "After swap function: ";
cout << "x = " << x << ", y = " << y << endl;
return 0;
}
Parameter Passing by Pointer
• Declare the parameters of swap as pointer variables so that they can contain addresses.
void swap(int *addr1, int *addr2)
• We will place the addresses of x and y into addr1 and addr2, respectively.
swap(&x, &y);

This technique is also known as Function call by reference


Parameter Passing by Pointer
#include <iostream>
using namespace std;
Memory space for swap function
void swap(int *addr1, int *addr2)
{ temp addr1 addr2
int temp;
temp = *addr1; ? &x &y
*addr1 = *addr2;
*addr2 = temp;
}
int main(void)
{
int x = 5, y = 10;
cout << "Before swap function: ";
cout << "x = " << x << ", y = " << y << endl;
• swap(&x,&y);
cout << "After swap function: ";
cout << "x = " << x << ", y = " << y << endl;
x 5 y 10
return 0;
} Memory space for main function

Output:
Before swap function: x = 5, y = 10
Parameter Passing by Pointer
#include <iostream> Memory space for swap function
using namespace std;
temp addr1 addr2
void swap(int *addr1, int *addr2)
{ 5 &x &y
int temp;
temp = *addr1;
*addr1 = *addr2;
*addr2 = temp;
}
int main(void)
{
int x = 5, y = 10;
cout << "Before swap function: ";
cout << "x = " << x << ", y = " << y << endl;
swap(&x,&y); x 10 y 5
cout << "After swap function: ";
cout << "x = " << x << ", y = " << y << endl; Memory space for main function
return 0;
}

Output:
Before swap function: x = 5, y = 10
After swap function: x = 10, y = 5
Reference Variables
• A reference is an additional name given to an existing memory
location Pointer: Reference:

x 9 x≡ref 9

ref

int x = 9;
int x=9;
int &ref = x;
int *ref;
ref = 6;//x = 6;
ref = &x;
*ref = 7;//x = 7;
Reference Variables
• A reference variable serves as an alternative name for an object.

• int m = 10;
• int &j = m; // j is a reference variable

• cout << "value of m = " << m << endl; // print 10


• j = 18;
• cout << "value of m = " << m << endl; // print 18
Parameter Passing by Reference
#include <iostream>
using namespace std;
void swap(int &ref1, int &ref2)
{
int temp;
temp = ref1;
ref1 = ref2;
ref2 = temp;
}
Output:
int main(void) Before swap function: x = 5, y = 10
{ After swap function: x = 10, y = 5
int x = 5, y = 10;
cout << "Before swap function: ";
cout << "x = " << x << ", y = " << y << endl;
swap(x,y);
cout << "After swap function: ";
cout << "x = " << x << ", y = " << y << endl;
return 0;
}

This is another way of function call by reference


Arrays and Pointers
#include <stdio.h>

int main(void)
{
char str[5] = {'H', 'E', 'L', 'L', 'O'};
char *ptr = &str[0];
printf(“ptr = %08x\n”, ptr);
printf(“str = %08x\n”, str);
return 0;
}
Arrays and Pointers
#include <stdio.h>

int main(void)
{
char str[5] = {'H', 'E', 'L', 'L', 'O'};
char *ptr = &str[0];
printf(“ptr = %08x\n”, ptr);
printf(“str = %08x\n”, str);
return 0;
} Output:
ptr = 0028ff17
str = 0028ff17
Arrays and Pointers
The array name is basically the name address content

of a pointer variable which contains 0x00000000


0x00000001
the starting address of the array
.
(address of the first element)
.
str 0x180A96e7
str
0x180A96e8
0x180A96f3
0x180A96e9
0x180A96f0
0x180A96f1
‘H’ ‘E’ ‘L’ ‘L’ ‘O’
0x180A96f2
0x180A96f3 ‘H’
0x180A96f4 ‘E’
0x180A96f5 ‘L’
0x180A96f6 ‘L’
0x180A96f7 ‘O’
.
.
Arrays and Pointers
The array name is basically the name address content

of a pointer variable which contains 0x00000000


0x00000001
the starting address of the array
.
(address of the first element)
.
str 0x180A96e7
str
0x180A96e8
0x180A96f3
0x180A96e9
0x180A96f0
0x180A96f1
‘H’ ‘E’ ‘L’ ‘L’ ‘O’
0x180A96f2
0x180A96f3 ‘H’

c = str[2]; is equivalent to 0x180A96f4 ‘E’


0x180A96f5 ‘L’
c = *(str + 2); 0x180A96f6 ‘L’
0x180A96f7 ‘O’
Base offset .
.
Arrays and Pointers
str

‘H’ ‘E’ ‘L’ ‘L’ ‘O’ ‘\0’

char str[6] = “HELLO";


Arrays and Pointers
str

‘H’ ‘E’ ‘l’ ‘L’ ‘O’ ‘\0’

ptr

char str[6] = “HELLO";


char *ptr = str;
ptr[2] = ‘l’;
Arrays and Pointers
str

‘H’ ‘E’ ‘l’ ‘L’ ‘O’ ‘\0’

ptr

char str[6] = “HELLO";


char *ptr = str;
ptr[2] = ‘l’;
ptr = ptr + 2;
Arrays and Pointers
str

‘H’ ‘E’ ‘l’ ‘L’ ‘u’ ‘\0’

ptr

char str[6] = “HELLO";


char *ptr = str;
ptr[2] = ‘l’;
ptr = ptr + 2;
ptr[2] = ‘u’;
address content

Arrays and Pointers 0x00000000


0x00000001
.
int A[3] = {3, 1, 8}; .

A 0x180A96e7

A 0x180A96e8
0x180A96f3
0x180A96e9
0x180A96f0
0x180A96f1
0x180A96f2

3 1 8 0x180A96f3
0x180A96f4
3
0x180A96f5

i = A[2]; is equivalent to 0x180A96f6


0x180A96f7
i = *(A + 2); 0x180A96f8
1
0x180A96f9
0x180A96fA

Base offset 0x180A96fB


0x180A96fC
8
0x180A96fD
0x180A96fE
Arrays and Pointers
int A[3] = {3, 1, 8};
A

3 1 8

ptr

int *ptr = A;
Arrays and Pointers
int A[3] = {3, 1, 8};
A

3 1 5

ptr

int *ptr = A;
*(ptr+2) = 5;//or: ptr[2]=5;
Arrays and Pointers
int A[3] = {3, 1, 8};
A

3 1 5

ptr

int *ptr = A;
*(ptr+2) = 5;//or: ptr[2]=5;
ptr = ptr + 2;
Arrays and Pointers
int A[3] = {3, 1, 8};
A

3 1 6

ptr

int *ptr = A;
*(ptr+2) = 5;//or: ptr[2]=5;
ptr = ptr + 2;
*ptr = 6;
Allocation of Memory
• Static Allocation: Amount of memory space required is determined in
advance (that is, at the compilation time) and memory space is
allocated to the program right before the program is executed.
For example,
int s;
The operating system allocates 4 bytes of memory to the program before its
execution.

• Dynamic Allocation: Amount of memory space required is


determined at run time (that is, after the program starts executing).
Memory space is allocated to the program at run time too.
Allocation of Memory
High-end

Run-time allocated
Stack

• Memory map

memory
STACK - This area is used for
function calls: return address,
argument and local variables Heap

Compile-time
static data
HEAP – This area is used for

allocated
memory
Dynamic Memory Allocation
Program
code
Static memory – reserved for global
and static variables live
Low-end
Dynamic Memory Allocation
 Dynamic allocation is useful when
• arrays need to be created whose extent is not known until run time
• complex structures of unknown size and/or shape need to be constructed as
the program runs
• objects need to be created and the constructor arguments are not known
until run time
 Pointers are used for dynamic allocation of memory
 Use the operator new to dynamically allocate space
 Use the operator delete to free this space later
The new Operator
 If memory is available, the new operator allocates memory space for
the requested object/array, and returns a pointer to (address of) the
memory allocated.
Pointer = new DataType;

Pointer = new DataType [IntExpression];

 If sufficient memory is not available, the new operator returns


NULL.
The delete Operator
 The delete operator de-allocates the object or array currently
pointed to by the pointer which was previously allocated at run-time
by the new operator.
• the freed memory space is returned to Heap
• the pointer is then considered unassigned
delete Pointer;

delete [] Pointer;

 If the value of the pointer is NULL there is no effect.


Example
Statically allocated
variable

int *ptr; ptr FDE0


ptr = new int; FDE1
*ptr = 22; 0EC4
FDE2
cout << *ptr << endl;
FDE3
delete ptr;
ptr = NULL;

0EC4
Output:
Dynamically 0EC5
22
22 allocated variable 0EC6
0EC7
Example

int *ptr; ptr FDE0


ptr = new int; FDE1
*ptr = 22; ?
FDE2
cout << *ptr << endl;
FDE3
delete ptr;
ptr = NULL;

0EC4
0EC5
0EC6
0EC7
Example

int *ptr; ptr FDE0


ptr = new int; FDE1
*ptr = 22; 0
FDE2
cout << *ptr << endl;
FDE3
delete ptr;
ptr = NULL;

0EC4
0EC5
0EC6
0EC7
Example
int *grades = NULL;
int numberOfGrades;

cout << "Enter the number of grades: ";


cin >> numberOfGrades;
grades = new int[numberOfGrades];

for (int i = 0; i < numberOfGrades; i++)


cin >> grades[i];

for (int j = 0; j < numberOfGrades; j++)


cout << grades[j] << " ";

delete [] grades;
grades = NULL;
Dynamic Allocation of 2D Arrays
• A two dimensional array is really an array of arrays (rows).
• To dynamically declare a two dimensional array of int type, you
need to declare a pointer to a pointer as:
int **matrix;
Dynamic Allocation of 2D Arrays
 To allocate space for the 2D array with r rows and c
columns:
 You first allocate the array of pointers which will point to the arrays (rows)
matrix = new int*[r];
 This creates space for r addresses; each being a pointer to an int.
 Then you need to allocate the space for the 1D arrays
themselves, each with a size of c
for(i=0; i<r; i++)
matrix[i] = new int[c];
Example
// create a 2D array dynamically
int rows, columns, i, j;
int **matrix;
cin >> rows >> columns;
matrix = new int*[rows];
for(i=0; i<rows; i++)
matrix[i] = new int[columns];
for(i=0; i<rows; i++)
for(j=0; j<columns; j++)
cin>>matrix[i][j];
// deallocate the array
for(i=0; i<rows; i++)
delete [] matrix[i];
delete [] matrix;
Memory Leak
• When you dynamically create objects, you can access them through
the pointer which is assigned by the new operator
• Reassigning a pointer, without deleting the memory it was pointing
to, is called a memory leak
• It results in loss of available memory space (recall that CPP doesn’t
have an automatic garbage collection mechanism, as Java has)
Memory Leak
int *ptr1 = new int; ptr1
int *ptr2 = new int; 8

*ptr1 = 8;
ptr2
*ptr2 = 5;
5
ptr2 = ptr1;

ptr1
8
This memory space is still
occupied despite the fact
that it is no longer being ptr2
accessed by our program 5
Memory Leak
 Inaccessible memory location
 Memory location that was allocated using new
 There is no pointer that points to this memory space
 It is a logical error and causes wastage of memory
Dangling Pointer
 A pointer that points to a memory location that has been de-
allocated.
 The result of dereferencing a dangling pointer is unpredictable.
Dangling Pointer

ptr1
int *ptr1 = new int;
8
int *ptr2;
*ptr1 = 8; ptr2
ptr2 = ptr1;
delete ptr1;
… ptr1


//accessing ptr2 here may ptr2
//result in unpredictable
//behavior

You might also like