Pointers
Pointers
Pointers
Pointers
Objectives
• Understand the concept pointers, declaration
and access.
• Use pointers to pass arguments to functions
by reference.
• Explain the close relationships between
pointers and arrays.
• Use arrays of pointers.
• Demonstrate basic pointer-based string
processing.
• Use pointers to functions
Introduction
• Variables are memory cells that can access by an
identifier.
• variables are stored in concrete places of the computer
memory.
• the computer memory is only a succession of 1 byte cells
(the minimum size for a datum), each one with a unique
address.
• A pointer is a variable which stores the address of another
variable.
• The only difference between pointer variable and
regular variable is the data they hold.
?????? Explain the concept of pointer in C++
There are two pointer operators in C++:
– & the address of operator
– * the dereference operator
• The & literally mean “address of” always produces the memory
address of whatever it precedes.
• The * operator, when used with pointers, either declares a
pointer or dereferences the pointer’s value.
• The dereference operator can be literally translated to
"value pointed by" .
• A pointer is simply the address of an object in memory.
• Generally, objects can be accessed in two ways:
– directly by their symbolic name, or
– indirectly through a pointer.
• The act of getting to an object via a pointer to it, is called
dereferencing the pointer.
• Pointer variables are defined to point to objects of a specific
type so that when the pointer is dereferenced, a typed object
is obtained.
• We generally do not decide where the variable is to be
placed – it is done automatically done by the compiler and
the operating system on runtime.
• But there are some cases in which we may be interested in
knowing where the variable is stored.
• Solution??? preceding the variable identifier by an
ampersand sign (&) "address of”.
– For example: ptr= &var;
• This would assign to variable ptr the address of variable var
, since when preceding the name of the variable var with the
ampersand ( & ) character we are no longer talking about
the content of the variable, but about its address in memory.
• We are going to suppose that var has
been placed in the memory address 1776
and that we write the following:
int var=25;
int x=var;
int * ptr = &var;
• The result will be the one shown in the
following diagram:
• The variable that stores the address of
another variable (like ptr in the previous
example) is what we call a pointer.
Declaring Pointers:
• Is reserving a memory location for a pointer
variable in the heap.
• Syntax: type * pointer_name ;
• ???declare a pointer variable called p_age:
int * p_age;
• Whenever the dereference operator, *,
appears in a variable declariation, the
variable being declared is always a pointer
variable.
Assigning values to pointers:
• p_age is an integer pointer. The type of a pointer is
very important.
• p_age can point only to integer values, never to
floating-point or other types.
• To assign p_age the address of a variable:
int age = 26; int * p_age; p_age = &age;
OR
int age = 26; int * p_age = & age;
• Two ways to print the value of age:
cout<<age;//prints value of age
cout<<*p_age;//dereferences p_age;
• The dereference operator produces a value that
tells the pointer where to point.
• cout<<p_age, would print an address(address of
age).
• You can assign a different value to age:
age = 13; //assigns a new value to age
*p_age = 13;
//assigns 13 as a value to the memory p_age points
at.
• N.B: the * appears before a pointer variable in only
two places:
– when you declare a pointer variable and when you
dereference a pointer variable (to find the data it points
to).
//more about pointers and the pointer operators, & and *
#...
int main()
{
int num = 123; // a regular integer variable
int *p_num; //declares an integer pointer
cout<< “num is ”<<num<<endl;
cout<< “the address of num is ”<<&num<<endl;
p_num = #// assign address of num in p_num;
cout<< “*p_num: ”<<*p_num<<endl; //prints value of num
cout<< “p_num: ”<<p_num<<endl; //prints value of P_num
return 0;
}
Pointer to void
• note that we can’t assign the address of a float
type variable to an integer pointer variable and
similarly the address of an integer variable can
not be stored in a float or character pointer.
• flaot y;
• int x;
• int *ip;
• float *fp;
• ip = &y; //illegal statement
• fp = &x; //illegal statement
• That means, if a variable type and pointer to type is
same, then only we can assign the address of variable to
pointer variable. And if both are different type then we
can’t assign the address of variable to pointer variable
but this is also possible in C++ by declaring pointer
variable as a void as follows:
void *p;
int x;
float y;
p = &x; //valid assignment
p = &y; //valid assignment
• The difficulty on void pointers is that, void pointers
can not be dereferenced. They are aimed only to store
address and the dereference operator is not allowed for
void pointers.
Arrays of Pointers
• If you have to reserve many pointers for many
different values, you might want to declare an array
of pointers.
int *iptr[10]; //reserves an array of 10
integer pointers
• The above statement will create the following
structure in RAM
iptr[4] = &age;// makes iptr[4] point to
address of age.
Pointer and arrays
• The concept of array goes very bound to the one of pointer. In fact, the
identifier of an array is equivalent to the address of its first element, like a
pointer is equivalent to the address of the first element that it points to, so in
fact they are the same thing.
• For example, supposing these two declarations:
int Numbers[20];
int * p;
• the following allocation would be valid:
p = numbers; //why?????
• At this point p and numbers are equivalent and they have the same
properties, with the only difference that we could assign another value to the
pointer p whereas numbers will always point to the first of the 20 integer
numbers of type int with which it was defined.
• Therefore, although the previous expression was valid, the following allocation
is not:
numbers = p;//??????
• Because numbers is an array (constant pointer),
and no values can be assigned to constant
identifiers.
• N.B: An array name is just a pointer, nothing more.
The array name always points to the first element
stored in the array.
int ara[5] = {10,20,30,40,50};
cout<< *(ara + 2); //prints ara[2];
• The expression *(ara+2) is not vague at all if you
remember that an array name is just a pointer that
always points to the array’s first element.
• Consider the following character array:
char name[] = “C++ Programming”;
char name[] = “C++ Programming”;
• What output do the following cout
statements produce?
• cout<<name[0]; // ____C__
• cout<<*name; // _____C__
• cout<<*(name+3); //_________
• cout<<*(name+0); //____C____
Question
• What is the two uses of * operator?
• Name its use???
Pointer Advantage
• You can’t change the value of an array name,
because you can’t change constants. This
explains why you can’t assign an array a new
value during a program’s execution:
• eg: if Cname is array of characters then:
Cname = “Football”; //invalid array
assignment;
• Unlike arrays, you can change a pointer
variable. By changing pointers, you can make
them point to different values in memory.
• Have a look at the following code:
#...
int main()
{ float v1 = 679.54;
float v2 = 900.18;
float * p_v;
p_v = &v1;
cout<< “\nthe first value is ”<<*p_v;
p_v = &v2;
cout<< “\nthe second value is ”<<*p_v;
return 0;
}
• You can use pointer notation and reference pointers as arrays with
array notation. The inner workings of arrays and pointer notation.
int main()
{
int ctr;
int iara[5] = {10,20,30,40,50};
int *iptr;
iptr = iara; //makes iprt point to array’s first element. Or iprt = &iara[0]
cout<< “using array subscripts:\n”
cout<< “iara\tiptr\n”;
for(ctr=0;ctr<5;ctr++)
{
cout<<iara[ctr]<< “\t”<< iptr[ctr]<< “\n”;
}
cout<< “\nUsing pointer notation\n”;
for(ctr=0;ctr<5;ctr++)
{
cout<< *(iara+ctr) << “\t” << *(iptr+ctr)<< “\n”;
}
return 0;
}
• Suppose that you want to store a persons name
and print it. Rather than using arrays, you can
use a character pointer.
int main()
{
G e o r g e \0
M e s f i n \0
J o h n \0
K i m \0
B a r b a r a \0
• Notice that much of the table is wasted space.
Each row takes 20 characters, even though the
data in each row takes far fewer characters.
• To fix the memory-wasting problem of fully
justified tables, you should declare a single-
dimensional array of character pointers.
• Each pointer points to a string in memory and
the strings do not have to be the same length.
• Here is the definition for such an array:
char *name [5] = {“George”,“Mesfin”,“John”,
“Kim”,“Barbara”};
• This array is a single-dimension array. The
asterisk before names makes this array an array
of pointers. Each string takes only as much
memory as is needed by the string and its
terminating zero.
• To print the first string, we should use:
cout<<*names; //prints George.
• To print the second use:
cout<< *(names+1); //prints Michael
• Whenever you dereference any pointer element
with the * dereferencing operator, you access one
of the strings in the array.
Pointer to pointer:
• As the memory address where integer, float or character is stored in can be
stored into a pointer variable, the address of a pointer can also be stored in
another pointer. This pointer is said to be pointer to a pointer.
• An array of pointer is conceptually same as pointer to pointer type. The
pointer to pointer type is declared as follows:
Data_type ** pointer_name;
• Note that the asterisk is double here.
int **p; //p is a pointer which holds the address of another pointer.
– E.g.:
char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;
• supposing the randomly chosen memory
locations of 7230 , 8092 and 10502 , could
be described thus:
Have a look at the following code:
int main()
{
int data;
int *p1;
int **p2;
data = 15;
cout<< “data = ”<<data<<endl;
p1 = &data;
p2 = &p1;
cout<< “data through p1 = ”<<*p1<<endl;
cout<< “data through p2 = ”<< **p2<<endl;
}
Dynamic memory:
• Until now, in our programs, we have only had as much memory as
we have requested in declarations of variables, arrays and other
objects that we included, having the size of all of them to be fixed
before the execution of the program.
• But, What if we need a variable amount of memory that can only be
determined during the program execution (runtime)? For example,
in case that we need a user input to determine the necessary
amount of space.
• The answer is dynamic memory, for which C++ integrates the
operators new and delete.
• Pointers are useful for creating dynamic objects during program
execution. Unlike normal (global and local) objects which are
allocated storage on the runtime stack, a dynamic object is
allocated memory from a different storage area called the heap.
Dynamic objects do not obey the normal scope rules. Their scope
is explicitly controlled by the programmer.
The New Operator
• In C++ new operator can create space dynamically i.e at run time, and
similarly delete operator is also available which releases the memory
taken by a variable and return memory to the operating system.
• When the space is created for a variable at compile time this approach is
called static. If space is created at run time for a variable, this approach
is called dynamic. See the following two lines: