Highlights of this lab:
In this lab, you will:- See the definition of a pointer.
- Observe the basic pointer operators.
- Master the mechanism for simple pointer manipulation.
- Realize how to use pointers to pass parameters by reference.
- Recognize how to use pointers with structures.
- Learn how pointers are used in conjunction with dynamic data .
- Discover what happens when a pointer goes into the unknown!
Definition of a Pointer.
Pointers are a type of variable that allow you to specify the address of a variable. They provide a convenient means of passing arguments to functions and for referring to more complex datatypes such as structures. They are also essential if you want to use dynamic data in the free store area. (That was a free look ahead to the dynamic data topic covered later in these notes.)You won't always know the specific value in a pointer, but you won't care as long as it contains the address of the variable you are after. You need to declare and initialize pointers just as you would other variables, but there are special operators that you need to use.Pointer Operators.
Here is a table showing the special characters used in C++ to declare and use pointers.dereference operator, indirection operator | This is used to declare a variable as a pointer. It is also used when you want to access the value pointed to by the pointer variable. | |
reference operator, address-of operator | Use before a variable to indicate that you mean the address of that variable. You'll often see this in a function header where the parameter list is given. | |
member selection operator | This is used to refer to members of structures |
Simple Pointer Use.
We'd better look at some examples to make this clear.First, we'll declare two ordinary integers, and also pointers to those integers.int alpha = 5; int beta = 20; int* alphaPtr = α int* betaPtr = βThe characters Ptr in the pointer variable name have no special significance. They are simply a memory aid for the programmer. Let's look more closely at one of the pointer declarations.
int* alphaPtr = αThe first part int*, tells the compiler to declare a pointer for integers. alphaPtr will be the name of that pointer. In the last part of that statement, α specifies that the address of the variable alpha is what should be assigned to the pointer variable.An aside here: It is also permissable to position the asterisk closer to the pointer variable name,
i.e. int *alphaPtr. However the convention seems to be moving towards placing the asterisk closer to the datatype.
Try to visualize memory after these declarations, thinking of the pointer variable as not having a particular value, simply links to the variables to which they had been assigned.
Now let's look at a trivial example of how to access this data.
*alphaPtr += 5;
*betaPtr += 5;
After these statements, it is only the contents of the alpha and beta variables that would be changed.
You might say, "What's the big deal here? I could just as easily have written this:"
alpha += 5;
beta += 5;
True, but typically pointers aren't used in such a simple manner. We just showed this to illustrate the use of pointer syntax.
Using Pointers to Pass Parameters by Reference.
A more realistic example of pointer use is to see how pointers can be used in passing parameters to a function by reference. In other words, you want to pass the addresses of the data to a function rather than the values of the data.Let's look at both pass by value and pass by reference to make sure we understand the difference. There is a little example in the C++ Syntax Web Pages (the section on Pointers) that illustrates how parameters are passed by value. Here's what that looks like:int a = 5; int b = 9; exchange(a,b); // main pgm function call ... void exchange(int x, int y) // pass by value { int temp; temp = x; x = y; y = temp; return; }Simple, direct - right? Well yes, but the values of a and b in the main program have not been changed! If that is what you really wanted to do, you should have used pointers to pass the parameters by reference.To do this, you need to change the function prototype and header to
void exchange(int & x, int & y)
Here is what the whole program looks like.
#include <string.h> #include <iostream> using namespace std; void exchange (int& x, int& y); int main () { int a = 5; int b = 9; cout << "This program exchanges 2 values." << endl; cout << "Values before the exchange:" << endl; cout << "a= " << a << " b= " << b << endl; exchange(a, b); // code that calls the function cout << "Values after the exchange:" << endl; cout << "a= " << a << " b= " << b << endl; } // function for passing by reference void exchange (int& x, int& y) { int temp; temp = x; x = y; y = temp; return; } // end exchange
Now, when the function is executed, the values of a and b will be changed in the main program. Next we'll look at how pointers are used with C++ structures.
Pointers and Structures
Let's start here by looking at an example of the structure STUDENT.struct STUDENT // define the structure { char name[20]; int id; int mark[3]; }; .... void main() { STUDENT stu; // declare an instance of the structureYou could simply pass the address of that instance directly to a function by coding:
function_name(&stu);You could also add a pointer declaration to reference that instance.
STUDENT * stuPtr = &stu;The general syntax to declare a pointer and associate it with the instance of a structure is this:
structure_name * pointer_name = & instance_name;Now, using this pointer to reference the structure instance, we could write:
(*stuPtr).id = 1999;The *, (the indirection operator), tells the compiler to use what stuPtr is pointing to. The parentheses are necessary because you want the compiler to evaluate the address in stuPtr before that value is connected to the id member delimeted by the dot operator. This is because the dot operator normally takes precedence over the indirection operator. (Remember order of precedence and order of evaluation in an expression? If not, grab your text and review these topics.)The syntax get awkward here though. i.e. (*stuPtr).id While that form of reference is technically correct, it is somewhat cumbersome, so C++ also allows another, easier form of reference.
stuPtr->id = 1999;This form eliminates the parentheses in a dot expression. We'll see more of this in the programming exercise for this week's lab exercise. The next section of these notes explains how pointers are necessary for a C++ construct called dynamic data.
Dynamic Data and Pointers.
Dynamic data items are called dynamic because they are created and deleted at run time. There are two operators used to perform these functions.new datatype | Used to allocate a dynamic variable. e.g. int *TmpPtr = new int; |
delete pointer | Used to deallocate a dynamic variable. e.g. delete TmpPtr; |
- You can't directly name a dynamic data variable as you can other regular variables. If you can't name it, then how do you reference it? The answer is that you do this with a pointer.
- When the new operation is executed, it returns a pointer to the location of the variable space in the free store.
int* TmpPtr = new int;The first part, int* TmpPtr, declares an integer pointer named tmpPtr. The second part, new int, creates a space in the free store, and returns a pointer to that space. The returned pointer is assigned to TmpPtr. This is typical of C++, i.e. you can accomplish a lot in a single line of code.You can declare arrays in free store as well as simple variables.
e.g. int* WeightPtr = new int [3];
To use this dynamic array element you could code:
WeightPtr[1] = 17; // Note: the "*" is not needed in an array reference.We'll see more of this in the programming exercise for this week's lab exercise. The whole idea of using dynamic data is to economize on memory space. So when you've finished with a piece of dynamic data you should release the space with the delete statement.
delete TmpPtr; delete [] WeightPtr;This releases space in the free store, but does not delete the pointer. Be careful here! If you try to use the pointer again, after the delete statement, you don't know what address will be in the pointer.Beware the dreaded segmentation fault, core dump! (See the next section for details.)To safeguard an inadvertent overwrite of a critical area in memory, it is advisable to set pointers to NULL after you delete the associated dynamic data space. e.g.
TmpPtr = NULL; WeightPtr = NULL;
this lab is taken from => ftp://ftp.cs.uregina.ca/pub/class/115/10-pointers/Longpointers.html
you can view the link for more details.