Skip to main content
Pointers
Department of Artificial Intelligence & Data Science,
National University of Computer & Emerging Sciences,
Islamabad Campus
From C++ Code to Process
• C++ source files
– .cpp; .h
• Binary files
– .o
• Executable (linux, Ubuntu, …)
– a.out
• Process
– Managed by OS
binary files
C++ source code
process
compiling
running
executable
linking
C++ Memory Models
• C++ leaves memory management mostly up to the
programmer:
ve++: write programs that use memory very
efficiently
Ve--: write programs that waste memory or do not
work at all
• For efficient program working, we need good
understanding of the memory models
C++ Memory Models
• Common errors caused by poor memory
management:
– Using a variable before it has been initialized
– Allocating memory for storage and not deleting it
– Using a value after it has been deleted
• What are the solutions?
– ….
Main Memory
CPU
Memory
Disk
Network
Video
Audio
Data Bus
shared by all processes
Virtual Memory
(How a CPU see’s a Process?)
• Continuous memory space
for all process:
– Set of locations as needed by a
process
0xffffffff
0
Organization of Virtual Memory: .text
• Program code and constant
– binary form
– loaded libraries
– code instructions
– space calculated at
compile-time
0xffffffff
0
text
Organization of Virtual Memory: .data
• Data: initialized global data in the
program
– Ex: int size = 100;
• BSS: un-initialized global data in
the program
– Ex: int length;
0xffffffff
0
text
data
bss
Organization of Virtual Memory: heap
• Heap: dynamically-allocated spaces
– Ex: new, delete
– dynamically grows as program runs
0xffffffff
0
text
data
bss
heap
Organization of Virtual Memory: stack
• Stack: local variables in functions
– support function call/return and
recursive functions
– grow to low address
0xffffffff
0
text
data
bss
heap
stack
Summary: Process Address Space
• text: program text/code
• data: initialized globals & static data
• bss: un-initialized globals & static data
• heap: dynamically managed memory
• stack: function’s local variables 0xffffffff
0
text
data
bss
heap
stack
Introduction to Pointers
• When we declare a variable, some memory is
allocated for it.
• Thus, we have two properties for any variable:
1. Its Address
2. and its Data value
E.g., char ch = ‘A’;
65
311
ch
Value
Memory Address
Introduction to Pointers
• How to get the memory-address of a variable?
• Address of a variable can be accessed through the
referencing operator “&”
– Example: &i will return memory location where
the data value for “i” is stored.
• A pointer is a variable, that stores an address.
Introduction to Pointers
• We can declare pointers as follows:
Type* <variable Name>;
– Example:
int* P;
- creates a pointer variable named “P”, that will
store address (memory location) of some int
type variable.
The address of Operator &
• The & operator can be used to determine the
address of a variable, which can be assigned to a
pointer variable
– Examples:
int* p1;
int v1=99;
p1 = &v1;
Now p1 points to the memory location,
where v1 is stored.
- v1 is an integer variable
- P1 is a integer pointer
Dereferencing Operator *
• C++ uses the * operator in yet another way with
pointers
– "The variable values pointed to by p" *p
– Here the * is the dereferencing operator
p is said to be dereferenced
int v1=99;
int* p= &v1;
cout<<“ P points to the value: “<<*p;
Dereferencing Pointer Example
int v1 = 0;
int* p1 = &v1;
*p1 = 42;
cout << v1 << endl;
cout << *p1 << endl;
v1 and *p1 now refer to
the same variable
Output:
42
42
Pointer Assignment and Dereferencing
• Assignment operator ( = ) is used to assign value
of one pointer to another
• Pointer stores addresses so p1=p2 copies an
address value into another pointer
int v1 = 55;
int* p1 = &v1;
int* p2;
p2=p1;
cout << *p1 << endl;
cout << *p2 << endl;
Output:
55
55
Example
char *string = “hello”;
const int iSize=8;
char* f(int x)
{
char *p;
p = new char[iSize];
return p;
}
0xffffffff
0
text
data
bss
heap
stack
Example
char *string = “hello”;
const int iSize=8;
char* f(int x)
{
char *p;
p = new char[iSize];
return p;
}
0xffffffff
0
text
data
bss
heap
stack
Variable Lifetime
• text:
– program startup
– program finish
• data, bss:
– program startup
– program finish
• heap:
– dynamically allocated
– de-allocated (free)
• stack:
– function call
– function return
0xffffffff
0
text
data
bss
heap
stack
Example
char *string = “hello”;
const int iSize=8;
char *f (int x)
{
char *p;
p = new char[iSize];
return p;
}
0xffffffff
0
text
data
bss
heap
stack
live after allocation; till
delete or program finish
when f() is
called
program
startup
Variable Initialization
• text:
– Read-only (once; e.g., constants)
• data
– on program startup
• bss:
– un-initialized (though some systems initialize with 0)
• heap:
– un-initialized
• stack:
– un-initialized
0xffffffff
0
text
data
bss
heap
stack
Dynamic Memory Allocation
• Used when space requirements are unknown at
compile time
• Most of the time the amount of space required is
unknown at compile time
• Dynamic Memory Allocation (DMA):-
– With Dynamic memory allocation we can
allocate/deletes memory (elements of an array) at
runtime or execution time.
Differences between Static and Dynamic Memory
Allocation
• Dynamically allocated memory is kept on the memory
heap (also known as the free store)
• Dynamically allocated memory cannot have a "name", it
must be referred to
• Declarations are used to statically allocate memory,
– the new operator is used to dynamically allocate
memory
Dynamic Memory Allocation
• Heap management in C++ is explicit:
Example
int main()
{
int *p;
p = new int;
return 0;
}
0xffffffff
0
text
data
bss
heap
stack
p
Example
0xffffffff
0
text
data
bss
heap
stack
#@%*&
p
int main()
{
int *p;
p = new int;
return 0;
}
Example
0xffffffff
0
text
data
bss
heap
stack
99
p
int main()
{
int *p;
p = new int;
*p = 99;
return 0;
}
Aliasing
int main()
{
int *p, *q;
p = new int;
*p = 99;
q = p;
return 0;
}
0xffffffff
0
text
data
bss
heap
stack
99
p
q
Aliasing
int main()
{
int *p, *q;
p = new int;
*p = 99;
q = p;
*q = 88;
return 0;
}
0xffffffff
0
text
data
bss
heap
stack
88
p
q
Aliasing
int main()
{
int *p, *q;
p = new int;
*p = 99;
q = p;
*q = 88;
delete q;
return 0;
}
0xffffffff
0
text
data
bss
heap
stack
$%#^&
p
q
Dangling Pointers
int main()
{
int *p, *q;
p = new int;
*p = 99;
q = p;
*q = 88;
delete q;
*p = 77;
return 0;
}
0xffffffff
0
text
data
bss
heap
stack
$%#^&
p
q
P and q are dangling pointers
WHY?
Dangling Pointers
• The delete operator does not delete the pointer, it
takes the memory being pointed to and returns it to
the heap
• It does not even change the contents of the pointer
• Since the memory being pointed to is no longer
available (and may even be given to another
application), such a pointer is said to be dangling
Avoiding a Dangling Pointer
• For Variables:
delete v1;
v1 = NULL;
• For Arrays:
delete[ ] arr;
arr = NULL;
Returning Memory to the Heap
• Remember:
– Return memory to the heap before undangling the
pointer
• What's Wrong with the Following:
ptr = NULL;
delete ptr;
Memory Leaking
int main()
{
int *p;
p = new int;
// make the above space unreachable; How?
p = new int;
// even worse…; WHY?
while (1)
p = new int;
return 0;
}
Memory Leaking
void f ( )
{
int *p;
p = new int;
return;
}
int main ( )
{
f ( );
return 0;
}
Memory Leaks
• Memory leaks when it is allocated from the heap
using the new operator but not returned to the
heap using the delete operator
Memory Leaking and Dangling Pointers
• Dangling pointers and memory leaking are evil
sources of bugs:
– hard to debug
•may appear after a long time of run
•may far from the bug point
– hard to prevent
• What should be the good programming practices while
using Pointers?
Pointers Data-Type
• Question:
Why is it important to declare the type of the
variable that a pointer points to?
Aren’t all memory addresses of the same length?
Pointers Type
• Answer:
- All memory addresses are of the same length,
– However, with operation “p++” where “p” is a
pointer the compiler needs to know the data
type of the variable “p” (to jump at next memory
location)
– Examples:
–If “p” is a character-pointer then “p++” will
increment “p” by one byte (next location)
–if “p” is an integer-pointer its value on “p++”
would be incremented by 4 bytes (next loc.)
Pointers Types
• Summary:
–Pointer is a data-type that stores addresses, it is
declared as follows: int* a; char* p; etc.
–The value stored in a pointer p can be accessed
through the dereferencing operator *
–The address of a memory location of a variable can
be accessed through the reference operator “&”.
Pointer Assignments (Aliasing)
• Some care is required making assignments to
pointer variables:
p1= p2; // changes the location that p1 "points" to
*p1 = *p2; // changes the value at location that
// p1 "points" to
Another Pointer Example
int i = 1;
int j = 2;
int* ptr;
ptr = &i; // ptr points to location of i
*ptr = 3; // contents of i are updated
ptr = &j; // ptr points to location of j
*ptr = 4; // contents of j are updated
cout << i << " " << j << endl;
Output:
3
4
Null Address
• Like a local variable, a pointer is assigned a random
value (i.e., address) if not initialized
• 0 is a pointer constant that represents the empty or
Null address
• Should be used to avoid dangling pointers
– Cannot Dereference a Pointer whose value is Null:
int *ptr = 0; OR int *ptr=NULL;
cout << *ptr << endl; // ERROR: ptr
// does not point to
// a valid address
Relationship Between Pointers and Arrays
• Arrays and pointers are closely related
– Array name is like constant pointer
– All arrays elements are placed in the consecutive
locations.
•Example:- int List [10]; List is the start address of
array
– Pointers can do array subscripting operations
We can access array elements using pointers.
•Example:- int value = List [2]; //value assignment
int* p = List; //address assignment
Relationship Between Pointers and Arrays (Cont.)
Effect:-
- List is an address, no need for &
- The bPtr pointer will contain the address of the first
element of array List.
– Element List[2] can be accessed by *( bPtr + 2 )
Relationship between Arrays and Pointers
• Arrays and pointers are closely related:
void main()
{
int numbers[]={10,20,30,40,50};
cout<<numbers[0]<<endl;
cout<<numbers<<endl;
cout<<*numbers<<endl;
cout<<*(numbers+1);
}
10
Address e.g., &34234
10
20
Arrays and Pointers
Array name is the starting address of the array
• Let int A[25];
int *p; int i, j;
• Let p = A;
• Then p points to A[0]
p + i points to A[i]
&A[j] == p+j
*(p+j) is the same as A[j]
Arrays and Pointers
Pointer Arithmetic
Only two types of arithmetic operations allowed:
1) Addition : only integers can be added
2) Subtraction: only integers be subtracted
Which of the following are valid/invalid?
Comparing Pointers
• If one address comes before another address in
memory, the first address is considered less than
the second address.
• Two pointer variables can be compared using C++
relational operators: <, >, <=, >=, ==
• In an array, elements are stored in consecutive
memory locations, E.g., address of Arr[2] will be
smaller than the address of Arr[3] etc.
Void Pointer
• void* is a pointer to no type at all:
•Any pointer type may be assigned to void *
int iVar=5;
float fVar=4.3;
char cVar=‘Z’;
int* p1;
void* vp2;
p1 = &iVar; // Allowed
p1 = &fvar; // Not Allowed
P1 = &cVar; // Not Allowed
vp2 = &fvar; // Allowed
vp2 = &cVar; // Allowed
vp2 = &iVar; // Allowed
This is a great advantage…
So, What are the limitations/challenges?
Accessing 1-Demensional Array Using Pointers
• We know, Array name denotes the memory address
of its first slot.
– Example:
int List [ 50 ];
int *Pointer;
Pointer = List;
• Other slots of the Array (List [50]) can be accessed
using by performing Arithmetic operations on Pointer.
• For example the address of (element 4th
) can be
accessed using:-
int *Value = Pointer + 3;
• The value of (element 4th
) can be accessed using:-
int Value = *(Pointer + 3);
Address Data
980 Element 0
982 Element 1
984 Element 2
986 Element 3
988 Element 4
990 Element 5
992 Element 6
994 Element 7
996 Element 8
998 Element 49
…
…
Accessing 1-Demensional Array
Address Data
980 Element 0
982 Element 1
984 Element 2
986 Element 3
988 Element 4
990 Element 5
992 Element 6
994 Element 7
996 Element 8
998 Element 49
…
…
….
….
int List [ 50 ];
int *Pointer;
Pointer = List; // Address of first Element
int *ptr;
ptr = Pointer + 3; // Address of 4th
Element
*ptr = 293; // 293 value store at 4th
element
address
}
986 293
Accessing 1-Demensional Array
Address Data
980 Element 0
982 Element 1
984 Element 2
986 Element 3
988 Element 4
990 Element 5
992 Element 6
994 Element 7
996 Element 8
998 Element 49
…
…
…
…
int List [ 50 ];
int *Pointer;
Pointer = List;
for ( int i = 0; i < 50; i++ )
{
cout << *Pointer;
Pointer++; // Address of next element
}
for ( int loop = 0; loop < 50; loop++ )
cout << Array [ loop ] ;
This is Equivalent to
We can access all element of List [50] using Pointers
and for loop combinations.
Accessing 2-Demensional Array
• Note that the statements
int *Pointer;
Pointer = &List [3];
• represents that we are accessing the address
of 4th
slot.
• In 2-Demensional array the statements
int List[ 5 ][ 6 ];
int *Pointer;
Pointer = &List [3];
Represents that we are accessing the address
of 4th
row
• or the address the 4th
row and 1st
column.
Address Data
980 Element 0
982 Element 1
984 Element 2
986 Element 3
988 Element 4
990 Element 5
992 Element 6
994 Element 7
996 Element 8
998 Element 50
…
…
Accessing 2-Demensional Array
– int List [ 9 ] [ 6 ];
– int *ptr;
– ptr = &List [3];
• To access the address of 4th
row
2nd
column:
– ptr++; // address of 4th
row 2nd
column
– (faster than normal array accessing
Why?)
– Equivalent to List [3][1] ;
302 304
300 306 308 310
314 316
312 318 320 322
326 328
324 330 332 334
338 340
336 342 344 346
350 352
348 354 356 358
362 364
360 366 368 370
374 376
372 378 380 382
386 388
384 390 392 394
398 400
396 402 404 406
1 2
0 3 4 5
0
1
2
3
4
5
6
7
8
Column
Row Memory address
Accessing 2-Demensional Array
• We know computer can perform only
one operation at any time (remember
fetch-decode-execute cycle).
• Thus to access List [3][1] element
(without pointer) two operations are
involved:-
– First to determine row List [3]
– Second to determine column List[3][1]
• But using pointer we can reach the
element of 4th
row 2nd
column (directly)
by increment our pointer value (which is
a single operation).
– ptr+1; // 4th
row 2nd
column
– ptr+2; // 4th
row 3rd
column
– ptr+3; // 4th
row 4th
column
302 304
300 306 308 310
314 316
312 318 320 322
326 328
324 330 332 334
338 340
336 342 344 346
350 352
348 354 356 358
362 364
360 366 368 370
374 376
372 378 380 382
386 388
384 390 392 394
398 400
396 402 404 406
1 2
0 3 4 5
0
1
2
3
4
5
6
7
8
Column
Row Memory address
Swapping variables using Pointers
void main() {
char a = ‘A';
char b = ‘Z';
char *Ptr1= &a;
char *Ptr2= &b;
char temp = *Ptr1;
*Ptr1 = *Ptr2;
*Ptr2 = c;
cout << a << b << endl;
}
;
Dynamic Memory Allocation
• Used when space requirements are unknown at
compile time
• Most of the time the amount of space required is
unknown at compile time
• Dynamic Memory Allocation (DMA):-
– With Dynamic memory allocation we can
allocate/deletes memory (elements of an array) at
runtime or execution time.
Differences between Static and Dynamic Memory
Allocation
• Dynamically allocated memory is kept on the memory
heap (also known as the free store)
• Dynamically allocated memory cannot have a "name", it
must be referred to
• Declarations are used to statically allocate memory,
– the new operator is used to dynamically allocate
memory
Pointing to Memory Allocated at Run Time
• int *ptr;
• ptr = new int;
• *ptr = 7;
• int *a;
• a = new int[3];
– *a = 300;
– *(a+1) = 301;
– *(a+2) = 302;
Returning Memory to the Heap
• How Big is the Heap?
– Most applications request memory from the heap when
they are running;
– It is possible to run out of memory (you may even have
gotten a message like "Running Low On Virtual
Memory")
– So, it is important to return memory to the heap when
you no longer need it
Returning Memory to the Heap
• The Opposite of new:
– The delete operator in C++
• delete ptr;
Dangling Pointers
• The delete operator does not delete the pointer, it
takes the memory being pointed to and returns it to
the heap
• It does not even change the contents of the pointer
• Since the memory being pointed to is no longer
available (and may even be given to another
application), such a pointer is said to be dangling
• ptr = NULL;
Returning Memory to the Heap
• Remember:
– Return memory to the heap before undangling the
pointer
• What's Wrong with the Following:
ptr = NULL;
delete ptr;
Returning Memory to the Heap
• For Arrays:
delete[ ] a;
a = NULL;
Memory Leaks
• Memory leaks when it is allocated from the heap
using the new operator but not returned to the
heap using the delete operator
• int *otherptr;
• otherptr = new int;
• *otherptr = 4;
• otherptr = new int;
Creating Dynamic 2D Arrays
Two basic methods:
1. Using a single Pointer
2. Using a Array of Pointers
Dynamic two dimensional arrays
1. Using a single Pointer
• Total elements in a 2D Array:
– m * n (i.e., rows * cols)
5 rows * 4 columns
= 20 elements
Target Approach=
• allocate 20 elements using dynamic allocation
• Use a single pointer to point and access those items.
Dynamic 2D Arrays
Dynamic 2D Array – Double Pointer
2. Using a Pointer that points to Array of Pointer
• Total elements in a 2D Array: M_rows * N_coulmns
Ptr2D
(Pointer to a Pointer)
Dynamic 2D Array – Double Pointer
Dynamic two
dimensional arrays
Can we vary size of each
column in Dynamic 2D Array
(using double pointer)
PP start of array of pointers
*PP First Address pointed by first row (sub array)
*(*PP) First value of first array
(*PP)++ Move to next address in the first array
PP++ Move to Next row (second array address
Dynamic 2D Array
(Varying Row Size)
Casting pointers
Pointers have types, so you cannot just do
int *pi; double *pd;
pd = pi;
Even though they are both just integers, C++ not
allows (Error)
Casting pointers
C++ will let you change the type of a pointer
with an explicit cast
int *pi; double *pd;
pd = (double*) pi;
Note: Values differenced after cast are
undermined (difference of memory size)
Home Work
- Manipulating a 3D Array
1. Using a single pointer
2. Using a triple pointer
3D Array Using
a single pointer
3D Array Using a
triple pointer
Constant Pointer
• A constant pointer is a pointer that is constant, such
that we cannot change the location (address) to which
the pointer points to:
char c = 'c';
char d = 'd';
char* const ptr1 = &c;
ptr1 = &d; // Not Allowed
int* const ptrInt=&v1; //ptr is constant pointer to int
Pointer to Constant 1/2
• we cannot set a non-const pointer to a const data-item
const int value = 5; // value is const
int *ptr = &value; // compile error: cannot convert const int* to int*
*ptr = 6; // change value to 6
const int value = 5;
const int *ptr = &value; // this is okay,
*ptr = 6; // not allowed, we cannot change a const value
Pointer to Constant 2/2
• A pointer through which we cannot change the value
of variable it points is known as a pointer to constant.
• These type of pointers can change the address they
point to but cannot change the value kept at those
address.
int var1 = 0;
const int* ptr = &var1;
*ptr = 1; // Not Allowed
cout<<*ptr;
char* and const
• const char *ptr : This is a pointer to a constant
character. You cannot change the value pointed by ptr,
but you can change the pointer itself. “const char *” is a
(non-const) pointer to a const char.
• char *const ptr : This is a constant pointer to
non-constant character. You cannot change the pointer p,
but can change the value pointed by ptr.
• const char * const ptr : This is a constant pointer
to constant character. You can neither change the value
pointed by ptr nor the pointer ptr.
C-String and Char Pointer
• A String: is simply defined as an array of characters
char* s;
// s is the address of the first character (byte) of the string
• A valid C string ends with the null character ‘0’
• Direct initialization char* <string Literal>;
char* s=“FAST”;
cout<<s<<sizeof(s);
cout<<++s<<sizeof(s);
char [ ] VS. char *
char A[20]=“FAST”; char* P=“FAST”;
1) A is an Array
2) A++; //invalid
3) sizeof(A) 20 Characters or bytes
4) A and &A points to same memory
address
5) A=“PAKISTAN”; //invalid
A is an address, “PAKISTAN” is the start
address where “PAKISTAN” string is stored
in memory.
6) A[0]=‘p’; //Valid
7) A is stored in stack
1) P is a pointer variable
2) P++; //Valid
3) Sizeof(P) 4 Characters or bytes
4) P points to start address where
characters are stored, and &P points to
address of pointer variable.
5) P=“PAKISTAN” //valid
6) P[0]=‘p’; //inValid
7) P is stored in Stack, “FAST” is stored in
“Text” section (Read-only)
C-String and Char Pointer
C-String and Char Pointer - Example
// Copying string using Pointers
char* str1 = “Self-conquest is the greatest victory.”;
char str2[80]; //empty string
char* src = str1;
char* dest = str2;
while( *src ) //until null character,
*dest++ = *src++; //copy chars from src to dest
*dest = ‘0’; //terminate dest
cout << str2 << endl; //display str2
Functions Pass by using Reference Pointer
• Pass-by-reference with pointer arguments
•Use pointers as formal parameters and
addresses as actual parameters
• Pass address of argument using & operator
– Arrays not passed with & because array name
already an address
– Pointers variable are used inside function
c
Pass by Reference Pointers–
Example1
void func(int *num)
{
cout<<"num = "<<*num<<endl;
*num = 10;
cout<<"num = "<<*num<<endl;
}
void main()
{
int n = 5;
cout<<"Before call: n = "<<n<<endl;
func(&n);
cout<<"After call: n = "<<n<<endl;
}
c
void compDouble(int* Ar)
{
for(int i=0;i<10;i++)
{ *Ar=(*Ar)*2;
Ar++;
}
}
void main()
{ int Arr[10]={0,1,2,3,4,5,6,7,8,9};
compDouble(Arr);
for(int i=0;i<10;i++)
cout<<Arr[i]<<endl;
}
c
Pass by Reference Pointers–
Example2
void compDouble(int* Ar)
{
for(int i=0;i<10;i++)
{ *Ar=(*Ar)*2;
Ar++;
}
}
void main()
{ int Arr[10]={0,1,2,3,4,5,6,7,8,9};
compDouble(Arr);
for(int i=0;i<10;i++)
cout<<Arr[i]<<endl;
}
c
Pass by Reference Pointers–
Example2
Address of character variable…
c
Questions (last lecture)
c
EXTRA Slides
c
Reference Variable and a Pointer
The main difference between C++ Reference vs Pointer is that
one is referring to another variable while the latter is storing the
address of a variable. ... An array of pointers can be created while
an array of references cannot be created. A null value cannot be
assigned to a reference but it can be assigned to a pointer.