CO1401 Week 11 Lecture

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 40

CO1401

Programming

Week 11
Pointers
Topic 1

Pointers

2 Programming
Memory

• Programs reside in memory. This includes:


• the program code itself (the instructions)
• data
• Data is contained in memory.
• The CPU is designed to work with memory locations.
Memory operations tend to be fast.
• A reference to a memory location which contains
some data will be faster than copying the data
around.
• This occurs with call by reference.
Hexadecimal

• Addresses tend to be given in hexadecimal, i.e. in base


16.
• Bits are on/off. They are binary.
• However, people find it cumbersome to use binary.
• Hexadecimal is base 16.
• Use the numerals 0 - 9 and then A (10), B (11), C(12),
D(13), E(14) and F(15).
• Hexadecimal is more compact.
• 16 is the fourth power of 2. So it is relatively easier to
write hexadecimal than decimal.
Hexadecimal

• A byte is 8 bits. You could express the range of


number using decimals (0-255) but it is more
convenient to use hexadecimal (00 to FF).
• 32 bits would be given using 4 bytes.
• I'm going to give some examples later taken from my
machine. This uses a 32-bit version of Windows,
hence the memory locations will be 8 numbers long: 4
bytes, each byte can be expressed using 2
hexadecimal numerals, e.g.
• 0x002BF8A8
Memory and variables

• Variables are stored at a location in memory.


• Every location in memory is accessed using an "address".
• Addresses are given in hexadecimal because we deal
with bytes (the next grouping up above bits) and then
machine addressing is always a multiple of a byte:
• a 8-bit machine
• a 16-bit machine
• a 32-bit machine
• a 64-bit machine
• All of these values lend themselves to hex.
Address

• You can obtain the address of a variable using the


ampersand symbol:

int i;
int j;
cout << &i << endl; // "the address of" i
cout << &j << endl; // "the address of" j

• 0027F988
• 0027F97C
Address

• A variable name is a label.


Storing an address

character
pointers variable

0x001C5000 ‘p’

0x001C5004 ‘a’

0x001C5008 ‘n’
Pointers

● Pointers are a special kind of variable. Pointers do not


store values. A pointer stores the memory location of
another variable. In other words, pointers "point at"
variables.
● A pointer variable is declared using an asterisk (*). The
asterisk is placed after the name of the data type of
the pointer and before the name of the pointer itself.
For example, the following code declares an interger
pointer named ptr:

int* ptr;
What is a pointer?

• Pointers do not store values.


• Pointers "point at" variables.
• A pointer stores memory locations. A memory location
is called an "address". Pointers "point at" a block of
memory.
• A pointer variable is declared using an asterisk.
• The asterisk is placed after the name of the data type of
the pointer and before the name of the pointer itself.
int* ptr;
float* fptrl
char* cptr;
What is a pointer?

• Pointers are given a datatype. However, this is the type of


data type that they point at. The pointers themselves are
identical.
• All pointers are the same size.

cout << sizeof ( int ) << endl; // 4 bytes


cout << sizeof ( myStruct ) << endl; // 12 bytes
cout << sizeof ( int* ) << endl; // 4 bytes
cout << sizeof ( myStruct* ) << endl; // 4 bytes
cout << sizeof ( StackClass* ) << endl; // 4 bytes
Why use pointers?

• Pointers are fast. The CPU is designed to process


numbers and memory addresses. The use of
addresses is efficient.
• Pointers can point at large, complex data structures
such as classes or structures. It is far faster to deal
with the address of complex data than with data itself.
• Pointer manipulation is efficient and easy.
• Pointers allow access to the full functionality of
classes, e.g. polymorphism.
• Pointers allow access to memory management.
Pointers

• The following two declarations are both syntactically


correct and identical in their meaning:

int* i;// Preferred form


int *i;// Older convention

• The first form of declaration is now the preferred


convention.
Pointers

• Every pointer takes up the same amount of memory.


• The data type of the pointer indicates the type of data
to which it can point.
• There are generic pointers (void*), but their use is
avoided in object oriented programming.
Dereferencing

• Need a way to obtain the value of the variable being


pointed at.
• If you want to output the value being pointed to by a
pointer then you need to include the asterisk, e.g.

cout << *ptr << endl;

• Obtaining the value being pointed at is called


dereferencing.
• Dereferencing is defined as "accessing the value referred
to by a reference".
Dereferencing example

• If there is possible ambiguity you can enforce


dereferancing through the use of brackets, e.g.

char* chPtr= new char;


*chPtr= 'a'; // dereferencing operator

cout << *chPtr<< endl; // dereferencing


// so it is the value that is output

(*chPtr)= 'a'; // dereferencing operator


cout << (*chPtr) << endl; // dereferencing
Pointer

int* ptr;

ptr = &i; // point at the address of the


// variable, where "i" is in memory
cout << ptr << endl; // the contexts of "ptr",
// i.e. the address of "i"
cout << *ptr << endl; // dereference,
// the value of the "i"
Pointer

ptr = &j; // point at the address of the variable,


// where "j" is in memory
cout << ptr << endl; // the contexts of "ptr",
// i.e. the address of "j"
cout << *ptr << endl; // dereference, the value of
// the "j"
Output of the previous slides

• By default, memory locations are given in


hexadecimal.

002BF8A8
4

002BF89C
7
Pointers
Examples

char ch = 'v';
char* cptr = &ch;

cout << cptr << endl; // address


cout << *cptr; // value
Examples

float f = 76.3f;
float* fptr = &f;

cout << fptr << endl; // address


cout << *fptr; // value
Topic 2

Memory allocation &


deallocation of simple
objects

24 Programming
Dynamic memory allocation

• In the last weeks we covered the STL and in particular


the vector class. One good things about vectors is that
they can be dynamically resized.
• "Dynamic" means whilst the programming is running.
• The vector class is a dynamic array.
• One of the most convenient thing about vectors is the
way in which we can dynamically increase the vector
by putting a new value onto the beginning or end of
the array.
Dynamic Memory Allocation

• Dynamic Memory Allocation allows the program to


request memory from the Operating System whilst the
program is running.
• For example, imagine that you have an array of student
records. You don't know how many students there may be
coming onto a course. You could declare a large array in
the hope that it will be large enough to cope. Even so you
couldn't be certain that it's big enough. You may end up
wasting memory, or alternatively being unable to cope
with a larger number of students.
• In Java the only way to declare a variable is to use dynamic
memory allocation.
Allocating memory: new

• In order to allocate memory you use the keyword


new.
• You need to give to tell the computer the size of
memory required. This is done by specifying the data
type when you use new.
• new returns a pointer. It returns the base address of
the block of memory allocated.
new

• allocates enough memory to store the specified data


type
• returns the address of the allocated memory
• need to specify the data type so that compiler knows
how big a memory block to allocate.

int* ptr = new(int);


Dynamic Memory Allocation

int main()
{
int* ptr = new(int);
*ptr = 3;
*ptr = *ptr + 4;
cout << *ptr << endl; delete(ptr);
}
Deallocating memory: new

• In order to deallocate memory you use the keyword


delete.
• You provide the name of the pointer.
• The pointers is providing the address of the block of
memory to be deleted.
• The operating system keeps track of all allocated
memory. It knows the size of the memory that was
allocated. All you need to provide is the base address of
then memory using a pointer.
• delete frees up the memory making it available for use
once more.
delete

• Frees the memory pointed at by the pointer


• It does not delete the pointer itself!

delete (ptr);
Dynamic Memory Allocation

• Be careful:

int* ptr = new (int); // allocate memory block


ptr = new (int); // allocate memory block

• ptr is now pointing at the second block of memory.

• It is no longer possible to access the first block of


memory! This is one way to cause memory leak.
Topic 3

Memory leaks

33 Programming
Memory leak

• A memory leak occurs when a program fails to release


allocated memory. If memory is allocated but never
released then the program slowly chokes. Should be
released when the program ends but this is not
guaranteed.
• There are specialist applications for tracking memory.
• Can enable memory leak detection in Visual Studio.
Memory leak

// Enable the debug heap functions.


#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
int main()
{
// Enable reporting of memory leaks
_CrtDumpMemoryLeaks();
}
Memory leak
Memory leak

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
int main()
{
int* p = new int;
*p = 5;
_CrtDumpMemoryLeaks();
}
Detected memory leaks!
Dumping objects ->
{55} normal block at 0x007F14E8, 4 bytes long.
Data: < > 05 00 00 00
Object dump complete.
Dynamic Memory Allocation: summary

• Detected memory leaks!


• Dumping objects ->
• {55} normal block at 0x007F14E8, 4 bytes long.
• Data: < > 05 00 00 00
• Object dump complete.
Memory leak

• By default report is sent to the Debug pane of the


Output window. (See previous slide).
• The debug message will show a number. You can cause
a break by inserting _crtBreakAlloc at the beginning of
the program and recompiling the program. This might
help you identify the location of the leak.

int main()
{
_crtBreakAlloc=-1;
}
Dynamic Memory Allocation: summary

● Dynamic Memory Allocation allows the program to


request memory from the Operating System whilst the
program is running.
● Two keywords:
• new: requests memory.
• delete: releases memory.

● memory leak: failing to release dynamically allocated


memory. If memory is allocated but never released then
the computer slowly chokes.

You might also like