CP Chapter 6
CP Chapter 6
1
2
Pointers …. Definition
Pointer: - A variable that stores address of another variable
A pointer is simply the address of a memory location and
provides an indirect way of accessing data in memory.
Variables are locations in the computer's memory which can be
accessed by their identifier (their name).
When a variable is declared, the memory needed to store its value
is assigned a specific location in memory (its memory address).
The memory allocation is the task of an operating system
eg. int myvar=25;
3 Cont..
x myvar
x = &myvar;
Declaring Pointers
Due to the ability of a pointer to directly refer to the value that it
points to, a pointer has different properties when it points to a
char than when it points to an int or a float.
Once dereferenced, the type needs to be known. And for that, the
declaration of a pointer needs to include the data type the pointer
is going to point to.
The declaration of pointers follows this syntax:
type * name;
8 Cont..
where type is the data type pointed to by the pointer. This type is
not the type of the pointer itself, but the type of the data the
pointer points to. For example:
int * num;
char * ch;
double * dec;
These are three declarations of pointers. Each one is intended to
point to a different data type, but, in fact, all of them are pointers.
The value of a pointer variable is the address to which it points.
For example, given the definitions
int a;
we can write:
num= &a;
9 Cont..
num= &a;
The symbol & is the address operator; it takes a variable as
argument and returns the memory address of that variable. The
effect of the above assignment is that the address of a is assigned
to num.
*num is equivalent to a
In general, the type of a pointer must match the type of the
data it is set to point to. A pointer of type void*, however, will
match any type.
This is useful for defining pointers which may point to data of
different types, or whose type is originally unknown
10 Cont..
A pointer may be cast (type converted) to another type. For
example, depending above three different declaration
ch= (char*) num;
converts num to char pointer before assigning it to ch.
11 Example
#include <iostream.h>
int main ()
{ int firstvalue, secondvalue;
int * mypointer; Output
mypointer = &firstvalue; firstvalue is 10
*mypointer = 10; secondvalue is 20
mypointer = &secondvalue;
*mypointer = 20;
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
}
12 Example 2
#include <iostream.h>
int main () Output
{ int firstvalue = 5, secondvalue = 15; firstvalue is 10
int * p1, * p2; Secondvalue is 20
p1 = &firstvalue; // p1 = address of firstvalue
p2 = &secondvalue; // p2 = address of secondvalue
*p1 = 10; // value pointed to by p1 = 10
*p2 = *p1; // value pointed to by p2 = value pointed by p1
p1 = p2; // p1 = p2 (value of pointer is copied)
*p1 = 20; // value pointed by p1 = 20
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
}
13
Dynamic Memory
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.
dynamic memory is program stack and heap.
static memory is program stack.
program stack is used for storing global variables and
stack frames for function calls.
The heap is used for dynamically allocating memory
blocks during program execution.
E.g. when the memory needed depends on user input.
14 Cont..
On dynamic memory cases, programs need to dynamically
allocate memory, for which the C++ language integrates
the operators new and delete.
Operators new and new[]
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 []. It
returns a pointer to the beginning of the new block of memory
allocated. 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 .
The second one is used to allocate a block (an array) of elements of
type , where number_of_elements is an integer value representing the
amount of these.
15 Cont..
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.
16 Cont..
Here, foo is a pointer, and thus, the first element pointed to by foo
can be accessed either with the expression foo[0] or the
expression *foo (both are equivalent).
The second element can be accessed either with foo[1] or
*(foo+1), and so on...
There is a substantial difference between declaring a normal array
and allocating dynamic memory for a block of memory using
new.
The most important difference is that the size of a regular array
needs to be a constant expression, and thus its size has to be
determined at compile time, whereas the dynamic memory
allocation performed by new allows to assign memory during
runtime using any variable value as size.
17 Cont..
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.
This is the purpose of operator delete, whose syntax is:
delete pointer;
delete[ ] pointer;
18 Cont..
delete pointer;
delete[ ] pointer;
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).
Example
19
#include <iostream.h>
int main ()
{ int i,n;
int * p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new int[i];
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> *(p+n);
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << *(p+n) << ", ";
delete[ ] p;
return 0;
}
20 Exercise
++myshort;
++mylong;
23 Cont..
*p++ // same as *(p++): increment pointer, and dereference
unincremented address
*++p // same as *(++p): increment pointer, and dereference
incremented address
++*p // same as ++(*p): dereference pointer, and increment the
value it points to
(*p)++ // dereference pointer, and post-increment the value it points to
*p = *q;
*p++ = *q++; ++p;
is Equivalent to:
++q;
Like always, parentheses reduce confusion by adding legibility to
expressions.
Example
24 char *str = "HELLO";
int nums[] = {10, 20, 30, 40};
int *ptr = &nums[0]; // pointer to first element
str++ advances str by one char (i.e., 1 byte) so that it points to
the second character of "HELLO", whereas ptr++ advances ptr
by one int (i.e., 4 bytes) so that it points to the second element of
nums.
For str for ptr
25 Cont..
It follows, therefore, that the elements of "HELLO" can be
referred to as *str, *(str + 1), *(str + 2), etc. Similarly, the
elements of nums can be referred to as *ptr, *(ptr + 1), *(ptr + 2),
and *(ptr + 3).
For example: depending above example subtracting two
pointers of the same type.
int *ptr1 = &nums[1];// ptr1= 0x23ff38
int *ptr2 = &nums[3];// ptr2= 0x23ff40
int n = ptr2 - ptr1; // n becomes 2
26 Pointers and Arrays
Arrays work like pointers to their first elements.
An array can always be implicitly converted to the pointer of the
proper type.
int myarray [20];
int * mypointer;
The following assignment operation would be valid:
mypointer = myarray; this means mypointer = &myarray[0];
The main difference is 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.
myarray = mypointer; // this is invalid
27
Cont..
For example:
int iarray[3] = {400, 657, 888};
int *iptr = iarray;// *iptr =& iarray[0];
assume address is given in the table so we can access address and array
elements as the following table .and also * (iarray+1) or *(iptr++) can
access value.
28 Example
#include <iostream.h>
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] << ", ";
return 0;
}
29 Pointers and String literals
String literals are arrays that contain all its characters plus the
terminating null-character.
Example: The following statement:
char * foo = "hello";
This declares an array with the literal representation for "hello",
and then a pointer to its first element is assigned to foo. Assume
“hello” is stored at 1702 memory address:
30 Cont..
#include <iostream>
using namespace std;
void Swap(int &x, int &y){ // pass-by-reference Output
int temp = x; 20, 10
x = y;
y = temp;
}
int main()
{
int i = 10, j = 20;
Swap(i,j);
cout <<i<< ", " <<j<< '\n';
return 0;
}
39 Typedefs
Typedef is a syntactic facility for introducing symbolic names for
data types. Just as a reference defines an alias for an object, a
typedef defines an alias for a type.
Its main use is to simplify otherwise complicated type
declarations as an aid to improved readability.
Here are a few examples:
typedef char *String;
Typedef char Name[12];
typedef unsigned int uint;
40 Cont..
The effect of these definitions is that String becomes an alias for
char*, Name becomes an alias for an array of 12 chars, and
uint becomes an alias for unsigned int.
Therefore: Stringstr;// is the same as: char *str;
Name name;// is the same as: char name[12];
uint n;// is the same as: unsigned int n;
41 Example:
#include <iostream>
using namespace std;
double Average (int nums[], int size)
{
typedef int Register;
double average = 0;
for (Register i = 0; i < size; ++i)
average += nums[i];
return average/size;
}
42 Cont..
int main()
{
int nums[3] = {5, 10, 15};
cout << Average (nums,3) << endl;
return 0;
}