Home

Pointer Types

 

Introduction

The computer has a significantly large memory, ranging in the millions of bytes. At one time, it may have to deal with different applications of various types. Each application has different requests and assignments. To better manage this, a good deal of the job is handed to the compiler. For example, as you declare and initialize variables, the compiler has to keep track of what variable is where? How much memory space a variable needs? Importantly, when is a variable needed? And when is a variable not needed anymore? For example, we saw that, when you declare a value variable, the compiler reserves a space for it in an area reserved and called the stack memory. When such a variable is not used anymore, for example when the application gets closed, the compiler removes that variable from memory to make that memory available to other applications:

Random Access Memory

This also means that the compiler is in charge of managing the memory used by value variables. Of course, the compiler needs to keep track of the various variables used in your program. In fact, each variables has an address. To know the address of a variable, which will not mean much to you anyway, you can precede it with the & operator when accessing. This operation should be performed using the cout class. Here is an example:

#include <iostream>
using namespace std;
using namespace System;

int main()
{
	int Nbr;
	cout << "Address of Number: " << &Nbr;
	Console::WriteLine();

	return 0;
}

This would produce:

Address of Number: 0012F3D0
Press any key to continue . . .

Pointer Declaration

In C++, instead of declaring a variable on the stack, the compiler reserves another area of memory called the heap. When declaring a variable, you can ask the compiler to "put" the variable in that area. To do this, precede the variable with an asterisk operator. Here is an example:

#include <iostream>
using namespace std;
using namespace System;

int main()
{
	int *Number;
	cout << "Address of Number: " << &Number;
	Console::WriteLine();

	return 0;
}

Such a variable is not a variable in the strict sense as that of a value. Instead, it is used to "point" to the memory location of another variable. For this reason, it is called a pointer to a variable or simply, a pointer.

Pointers allow you to manage computer memory and resources. When you declare a variable, the compiler reserves an amount of memory for that variable and waits for you to use that section of memory. If you declare a variable but do not use it throughout the life time of your program, that section of memory would have been busy, holding garbage, until your program ends. That section of memory would not be available to any other variable and you cannot prevent the compiler from creating it, as long as the unused variable exists. Therefore, another reason you would prefer pointers over regular variables is because pointers give you more control over the use of computer memory. Pointers allow you to decide when you need to use memory for a variable and when to free that memory space even if the program is still running.

Pointers allow you to create callback functions. These are functions whose name can be used as variables. This allows a function to be assigned as a value and to be passed as an argument. Something that is not possible with regular functions.

When declaring a pointer, the asterisk (*) lets the compiler know that the variable that follows is a pointer. There are three ways you can type the asterisk. These are

DataType* PointerName;
DataType * PointerName;
DataType *PointerName;

By default, it does not matter how you append the *, the compiler will know that the variable that follows is a pointer, as long as the word or group of words on the left side of the asterisk represents a valid data type.

Pointer Initialization

If you declare a value variable, you can initialize it with an appropriate value of its type. Here is an example:

#include <iostream>
using namespace std;
using namespace System;

int main()
{
	int Number = 224;
	cout << "Address of Number: " << &Number;
	Console::WriteLine();

	return 0;
}

If you declare a pointer, because it doesn't hold an explicit value like a value variable, you cannot just initialize it with any value: you would receive an error. If you want, you initialize it with 0, considered the null value. Here is an example:

#include <iostream>
using namespace std;
using namespace System;

int main()
{
	int Nbr = 224;
	int *Number = 0;
	
	Console::WriteLine();

	return 0;
}

Because a pointer "points" to another variable, to initialize it, you can assign it a declared and initialized variable preceded with the ampersand operator &. Here is an example:

#include <iostream>
using namespace std;
using namespace System;

int main()
{
	int Nbr = 224;
	int *Number = &Nbr;
	
	Console::WriteLine();

	return 0;
}

You can also initialize a pointer on a different line, after declaring it. This time, you should not use the asterisk on the pointer, but the compiler should know that the pointer will point to a variable's address. Therefore, the name of the variable will still use the & operator. This is done as follows:

using namespace System;

int main()
{
	int Nbr = 224;
	int *Number;
	
	Number = &Nbr;
	
	Console::WriteLine();

	return 0;
}

Just like a regular variable has an address, a pointer, as a variable, has an address too. To find out the address of a pointer variable, type the ampersand on its left, without the *.

Once you have declared and initialized a pointer variable, it holds the same value as the variable it points to. To display the value that a pointer holds, use its name preceded by the *. Here is an example:

using namespace System;

int main()
{
	int Nbr = 224;
	int *Number;
	
	Number = &Nbr;
	
	Console::Write("Number1: ");
	Console::WriteLine(Nbr);
	Console::Write("Number2: ");
	Console::WriteLine(*Number);

	return 0;
}

The program would produce:

Number1: 224
Number2: 224
Press any key to continue . . .

If you want to display the value held by a pointer, make sure you know what variable the pointer is pointing to. In other words, make sure you initialize it. If you attempt to display the value of an un-initialized pointer, the compiler would throw an error and would stop. Therefore, before accessing the value of a pointer, know what value that pointer is holding. Otherwise, wait until you have initialized it before accessing its value:

You do not have to always initialize either the pointer or the variable it is pointing to. You can first declare both the variable and a pointer, then initialize them later on, when needed.

Once you have declared a variable and assign it to a pointer, during the course of your program, the value of a variable is likely to change but as long as the pointer points to the same variable, it would hold the same value as the variable it points to.

A Pointer to a Pointer

Instead of pointing to a regular variable, a pointer can be made to point to another pointer. To apply this, always remember that you must specify what target a pointer is pointing to. Consider the following example:

using namespace System;

int main()
{
    int value = 26;
    int *pointer;

    pointer = &value;

    Console::WriteLine(" Value   = {0}", value);
    Console::WriteLine("*Pointer = {0}", *pointer);
    
    return 0;
}

This would produce:

Value   = 26
*Pointer = 26
Press any key to continue . . .

In this program, if necessary, you can declare a new variable that is a pointer that itself points to another pointer. When declaring such a variable, precede it with two *. After declaring the pointer, before using it, you must initialize it with a reference to a pointer, that is, a reference to a variable that was declared as a pointer. Here is an example:

using namespace System;

int main()
{
    int value = 26;
    int *pointer;
    int **pointerToPointer;

    pointer = &value;
    pointerToPointer = &pointer;

    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}", **pointerToPointer);
    
    return 0;
}

This would produce:

Value   = 26
 *Pointer = 26
**Pointer = 26
Press any key to continue . . .

Just as demonstrated earlier, after initializing a pointer, if you change the value of the variable it points to, the pointer would be updated. Consider the following program:

using namespace System;

int main()
{
    int value = 26;
    int *pointer;
    int **pointerToPointer;

    pointer = &value;
    pointerToPointer = &pointer;

    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}\n", **pointerToPointer);
    
    value = 4805;

    Console::WriteLine("After changing the value of the main variable...");
    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}\n", **pointerToPointer);

    return 0;
}

This would produce:

Value   = 26
 *Pointer = 26
**Pointer = 26

After changing the value of the main variable...
  Value   = 4805
 *Pointer = 4805
**Pointer = 4805

Press any key to continue . . .

Notice that, by changing the value of the original variable, when accessing its pointer or the pointer to its pointer, they reflect the new value. In the same way, instead of (directly) changing the value of the variable, you can change the value of its pointer. You can also change the value of the pointer to its pointer: all variables would be updated. Consider the following program:

using namespace System;

int main()
{
    int value = 26;
    int *pointer;
    int **pointerToPointer;

    pointer = &value;
    pointerToPointer = &pointer;

    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}\n", **pointerToPointer);
    
    value = 4805;

    Console::WriteLine("After changing the value of the main variable...");
    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}\n", **pointerToPointer);

    *pointer = -728;

    Console::WriteLine("After changing the value of the main variable...");
    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}\n", **pointerToPointer);

    **pointerToPointer = 945580;

    Console::WriteLine("After changing the value of the main variable...");
    Console::WriteLine("  Value   = {0}", value);
    Console::WriteLine(" *Pointer = {0}", *pointer);
    Console::WriteLine("**Pointer = {0}\n", **pointerToPointer);

    return 0;
}

This would produce:

Value   = 26
 *Pointer = 26
**Pointer = 26

After changing the value of the main variable...
  Value   = 4805
 *Pointer = 4805
**Pointer = 4805

After changing the value of the main variable...
  Value   = -728
 *Pointer = -728
**Pointer = -728

After changing the value of the main variable...
  Value   = 945580
 *Pointer = 945580
**Pointer = 945580

Press any key to continue . . .

Type Defining a Pointer

The C++ language also allows you to type define a pointer to a data type. To use this feature, type the typedef keyword, followed by a known data type, followed by an asterisk and followed by a common for the pointers you want to create. Here is an example:

typedef int *Positive;

After using the typedef keyword like this, the Positive word become synonym to a pointer to int. It can be used to declare variables that are pointers to an integer. Here is an example:

// Programmer-defined data type
typedef int *Positive;

Positive Age, Category;

In this example, Age is a pointer to int; so is Category.

To hint that the name of a variable is a pointer, it is a tradition to start it with p, P, ptr, or Ptr. Many of the pointers you will encounter in the Visual Component Library and in the MSDN documentation use this convention. The pointers we have seen so far could be declared as follows:

int *pAge;
unsigned int *ptrCategory;
double* PSalary;
long double * PtrDenominator;
double *PHourlySalary, *PWeeklySalary;

typedef int *PPositive;

Positive pAge, pCategory;
 

Previous Copyright © 2006 FunctionX, Inc. Next