Sei sulla pagina 1di 6

AJ/Handout 13 -1- Object-Oriented Programming

Lesson 13
Objectives
 Introduction to Pointers
 Addresses and Pointers
 The Address-of Operator &
 Pointers and Arrays
 Pointers and Functions
Introduction to Pointers
As their name specifies Pointer is something to point. Like we have some examples
 Accessing array elements
 Passing arguments to a function when the function needs to specify the original arguments
 Passing arrays and strings to functions
 Obtaining memory from the system
 Creating data structures like such as linked lists
Pointers are important features of C and C++. Whilst other languages like java, VB have no idea of
pointers, however, java uses reference that is sort of pointers. Though the same things can be
carried out without using pointers, like we can access arrays without using pointers similarly
passing value by reference to functions is possible. So subsequently we will see the difference and
enhancements possible by using pointers. Like their vitality is judged by creating linked lists and
binary trees in data structures. In fact many features of C++ those are not unfolded so far, needed
pointers to be utilized properly.
Address and Pointers
Idea behind pointers is not very complex. We start our discussion from the basic. Each byte in
memory has a distinct address. Like the daily life addresses these addresses are consecutive
starting from some specific number, moves on and ends at some number. Our programs when it
loaded into memory, occupies a certain range of these addresses. It means that each functions,
variable or what else we have in the program listing starts at a particular address.
The Address of Operator &
We can find the address occupied by a variable by using the address-of operator &. Here is a
program which shows how is it possible.
// varaddr.cpp
// addresses of variables
#include <iostream>
using namespace std;
AJ/Handout 13 -2- Object-Oriented Programming

int main()
{
int var1 = 11; //define and initialize
int var2 = 22; //three variables
int var3 = 33;
cout << &var1 << endl //print the addresses
<< &var2 << endl //of these variables
<< &var3 << endl;
return 0;
}
Output: 0x8f4ffff4 and so on.
It would simply display the addresses of these variables. One thing must be kept in mind that
addresses are totally different than the contents of that address. The insertion operator << interprets
it as hexadecimal as shown in result with prefix 0x. Further you can observe that the addresses are
differed by 2 so this is because each integer took two bytes. We already talked about integer
variable that may have 2 or 4 bytes depending of system. One thing more, the addresses are in
descending order because the local variables are stored on stack, which grows downward in the
memory. If we use global variables they would result in ascending order since they are stored at
heap, which grows upward.
Don’t confuse yourself address-of operator with the reference operator ‘&’, preceded by a variable
name.
Pointer variables
In above example we see how to find and print the memory addresses which keep user data. But
this is not very elegant. Our interest lies in those variables which contain memory addresses.
Addresses are stored in same fashion we same our integer, float etc data. The variables which
contain memory addresses are known as pointer variables or simply pointers.
Now question arise what is the data type of pointer variable? It is not the same as basic data type.
Let we see in the next example program.
// ptrvar.cpp
// pointers (address variables)
#include <iostream>
using namespace std;
int main()
{
int var1 = 11; //two integer variables
int var2 = 22;
cout << &var1 << endl //print addresses of variables
AJ/Handout 13 -3- Object-Oriented Programming

<< &var2 << endl << endl;


int* ptr; //pointer to integers
ptr = &var1; //pointer points to var1
cout << ptr << endl; //print pointer value
ptr = &var2; //pointer points to var2
cout << ptr << endl; //print pointer value
return 0;
}
So to define a pointer variable we use the statement int* ptr,ptr2; (pointer to integer)
In short, a pointer contains a memory address. However, it must be given some value, or it will
point to an address we don’t want it to point. Wrong pointer values can result in system crashes
and are difficult to debug, since compiler gives no warning. So we must be very sure that given
address is a valid one. We cannot define a pointer generally because compiler needs to know
“pointer to which variable” is used. C++ also allows using the user-defining data type pointers.
char* cptr;
float* fptr;
distance* distptr;
and so on.
Syntax
We can put the asterisk on either closer to the variable name or to the type. Both are valid.
char* ptr, *ptr2;
char *ptr, *ptr2; etc
Pointers must have a value
An address like 0x8ffff4 can be thought of a pointer constant and a pointer like ptr can be thought
of pointer variable. So a pointer variable can have a constant. As in earlier data types if there is no
value in variable it contains some garbage value here in case of pointer it could have some garbage
value as a memory address. So it must be properly initialized before being utilized.
Accessing the Variable Pointed To
Suppose we have a variable but we don’t know its contents. Though it seems very odd but in some
cases we really don’t know; like if we don’t have initialized the variable and we want to see the
garbage value in it just imagine. Then we simply have to store the variable in a pointer and display
the pointer just by putting asterisk before its name. That is demonstrated in that example.
// ptracc.cpp
// accessing the variable pointed to
#include <iostream>
using namespace std;
int main()
AJ/Handout 13 -4- Object-Oriented Programming

{
int var1 = 11; //two integer variables
int var2 = 22;
int* ptr; //pointer to integers
ptr = &var1; //pointer points to var1
cout << *ptr << endl; //print contents of pointer (11)
ptr = &var2; //pointer points to var2
cout << *ptr << endl; //print contents of pointer (22)
return 0;
}
When we use an asterisk before a pointer, like *ptr, that is called the dereference operator or
content of operator or indirection operator. It means the value of variable pointed to by. Thus the
expression *ptr represents the value of the variable pointed to by ptr. We can also perform some
operations to variable directly.
Note here in this case * not for pointer to but it is for indirection. That is why, accessing the value
by this way is called indirect addressing or sometime dereferencing, the pointer.
Here is a summary of all what we have learn.
int v; //defines variable v of type int
int* p; int *p; //defines p as a pointer to int
p=&v; // assigns address of variable v to pointer p
v=3; //assigns 3 to v
*p=3; //also assigns 3 to v
Pointer to void
Now we see a new characteristic of pointer. It is not allowed to use one data type pointer for
another data type pointer. For example;
float flovar=98.6;
int* ptrint=&flovar; //Error: can’t assign a float* to int*.
However, here is an exception to it. There is a sort of general purpose pointer that can point to any
data type. This is called pointer to void, and is defined as;
void* ptr;
Things will clear further in this example.
// ptrvoid.cpp
// pointers to type void
#include <iostream>
using namespace std;
int main()
{
int intvar; //integer variable
AJ/Handout 13 -5- Object-Oriented Programming

float flovar; //float variable

int* ptrint; //define pointer to int


float* ptrflo; //define pointer to float
void* ptrvoid; //define pointer to void

ptrint = &intvar; //ok, int* to int*


// ptrint = &flovar; //error, float* to int*
// ptrflo = &intvar; //error, int* to float*
ptrflo = &flovar; //ok, float* to float*

ptrvoid = &intvar; //ok, int* to void*


ptrvoid = &flovar; //ok, float* to void*
return 0;
}
If we have some obvious reason to assign a *flovar to a *int, we have to use reinterpret_cast. Like
shown here;
ptrint=reinterpret_cast<int*>(flovar);
ptrflo=reinterpret_cast<float*>(intvar);
But this is not recommended.
Pointers and Arrays
There is a close association between pointers and arrays. We already observed how to access arrays
and strings in previous lectures. It is surprising to know that arrays can be accessed using pointers.
As described in this example.
// ptrnote.cpp
// array accessed with pointer notation
#include <iostream>
using namespace std;

int main()
{ //array
int intarray[5] = { 31, 54, 77, 52, 93 };

for(int j=0; j<5; j++) //for each element,


cout << *(intarray+j) << endl; //print value
return 0;
}
Here the expression *(intarray+j) have the same affect as intarray[j] in any other program and
output would be same. But how do we interpret it? Actually name of array is its address and in the
expression j is being added to address. For any instance say j=3 then 3 is added to address of array,
AJ/Handout 13 -6- Object-Oriented Programming

which is fourth element of array 52. Don’t confuse that it would add 3 bytes to address. Also it
does not make any sense.
C++ compiler is smart enough to deal with addresses. Also it knows that intarray is of type int
because it was declared in that way. So when it sees the expression intarray+3, it interprets it as
the address of the fourth element of array, not the fourth byte. Also we want the value at that
address so we have used the dereference operator (*). That is why, it is compulsory to put array
type before defining it. Since compiler performs arithmetic accordingly for integer, float, double
etc.
Pointer Constants and Pointer Variables
In above example we have we have used *(intarray+j), can we use the expression *(intarray++)?
The answer is no. Since we can’t increment a constant, like there is no sense of using 7++. (In
multitasking system, variable addresses may change during program execution. An active program
may be swapped out to the disk and then reloaded at a different memory location. However, this
process in invisible in our program.)
But while we can’t increment a constant (address), you can increment a pointer that holds an
address. As given in example below.
// ptrinc.cpp
// array accessed with pointer
#include <iostream>
using namespace std;
int main()
{
int intarray[] = { 31, 54, 77, 52, 93 }; //array
int* ptrint; //pointer to int
ptrint = intarray; //points to intarray

for(int j=0; j<5; j++) //for each element,


cout << *(ptrint++) << endl; //print value
return 0;
}
Here expression *(ptrint++) is resulting same as *(intarray+j).

Potrebbero piacerti anche