header
//-----------------------------------------------
//
// Program: Pointers
// File: Pointers.cpp
//
// Purpose: demonstrate pointer variables.
//
// Single-step through this program to see how the
// variables change. Add the following to the watch
// window: intvar, &intvar, intptr, *intptr.
//
// D. Searls
// Asbury College
// April, 1998
//-----------------------------------------------

#include <iostream>

using namespace std;

int main()
{
  int intvar = 4; // Allocate space for an integer and initialize
                  // the value to four.

  int* intptr = NULL; // Allocate space for a pointer to an integer
                      // and initialize the pointer to NULL. This
                      // space will not contain an integer value
                      // but rather, the address of an integer value.
                      // A valid address must be assigned before
                      // attempting to access the integer value at
                      // that address.
                      
  cout << intvar << endl;
  cout << &intvar << endl;
  cout << intptr << endl;
  cout << &intptr << endl << endl;

  // Assign to intptr the address of intvar. Notice in the watch
  // window that intptr and &intvar are the same and that *intptr
  // and intvar are the same.
  
  intptr = &intvar;
  
  cout << intptr << endl;
  cout << *intptr << endl << endl;

  // Change the value of intvar and note that the value of *intptr
  // also changes.

  intvar = 1000;
  
  cout << intvar << endl;
  cout << *intptr << endl << endl;

  // Change the value of *intptr and note that the value of intvar
  // also changes.

  *intptr = 2000;
  
  cout << intvar << endl;
  cout << *intptr << endl << endl;

  // Pointer variables are very seldom used in this way. Normally,
  // space is dynamically allocated to store data and the address
  // of that allocated memory assigned to a pointer variable. If
  // the attempt to allocate memory fails (because there is no
  // more memory) then a NULL pointer is assigned to the pointer
  // variable. Typically, you should check for this.
  
  intptr = new (nothrow) int;

  if (intptr == NULL)
  {
    cout << "Allocation of memory failed!" << endl;
    exit(0);
  }
  
  cout << intptr << endl;
  cout << *intptr << endl << endl;
  
  
  *intptr = 3000;
  cout << *intptr << endl;
  
  (*intptr)++;
  cout << *intptr << endl << endl;

  // Memory that has been dynamically allocated using new can be
  // returned to the free space or heap. It is a grave logical
  // mistake to access a pointer after the corresponding memory
  // has been returned to the heap. It is not a syntax error, but
  // the values stored there are meaningless.

  cout << intptr << endl << endl;
  delete intptr;
  cout << intptr << endl;               // Severe logic error!
  cout << *intptr << endl << endl;      // Severe logic error!


  // It is often a good idea to assign the NULL value to a
  // pointer following the delete operation. This helps guard
  // against improper use of the pointer variable.

  intptr = NULL;
  
  cout << intptr << endl << endl;

  // It is a severe logical error to try to access data at an
  // invalid address. The results are not exactly predictable
  // but they are never good. In the statement below, an attempt
  // is made to access that data at the NULL address (namely zero).
  // This will cause the program to crash because of a memory
  // violation error.

   intvar = *intptr;  // Don't EVER do this!
  
  return 0;
}