// ==========================================================================
// $Id: references.cpp,v 1.1 2009/10/08 18:04:55 jlang Exp $
// CSI2372 example references vs. pointer
// ==========================================================================
// (C)opyright:
//
//   Jochen Lang
//   SITE, University of Ottawa
//   800 King Edward Ave.
//   Ottawa, On., K1N 6N5
//   Canada. 
//   http://www.site.uottawa.ca
// 
// Creator: jlang (Jochen Lang)
// Email:   jlang@site.uottawa.ca
// ==========================================================================
// $Log: references.cpp,v $
// Revision 1.1  2009/10/08 18:04:55  jlang
// Added const pointer vs. references example
//
//
// ==========================================================================
#include <iostream>
#include <sstream>

using std::cout;
using std::endl;
using std::hex;
using std::dec;

using std::istringstream;

/**
 * Pass by reference 
 */
void fctA( int& _passByRef ) {
  _passByRef *= 5;
  cout << _passByRef << " at address: " << hex 
       << &_passByRef << dec << endl;
  // Cannot assign to an address
  // &_passRef = ...
  return;
}

/**
 * Pass by pointer 
 */
void fctB( int* _passByPtr ) {
  *_passByPtr *= 5;
  cout << *_passByPtr << " at address: " << hex 
       << _passByPtr << dec; 
  cout << " pointer at " << hex << &_passByPtr << dec << endl;
  // Can change pointer -- does not affect outside calling context
  _passByPtr = 0;
  return;
}


/**
 * Pass by pointer const 
 */
void fctC( int * const _passByPtr ) {
  *_passByPtr *= 5;
  cout << *_passByPtr << " at const address: " << hex 
       << _passByPtr << dec;
  cout << " pointer at " << hex << &_passByPtr << dec << endl;
  // Cannot change pointer
  // _passByPtr = 0; // will result in compile error
  // But can cast const away
  int b = -5;
  int** ptr2ptr = const_cast<int**>(&_passByPtr); 
  *ptr2ptr = &b; // now change the pointer not the content
  cout << *_passByPtr << " at formerly const address: " << hex 
       << _passByPtr << dec;
  cout << " pointer at " << hex << ptr2ptr << dec << endl;
  return;
}


int main(int argc, char* argv[] ) {
  int val = 1;
  if ( argc > 1 ) {
    cout << argv[0] << " : " << argv[1] << endl;
    istringstream is( argv[1] );
    is >> val;
  }
  int tmp = val; // store original value
  fctA(val);
  cout << val << " at address: " << hex << &val
       << dec << " after call by reference" << endl;
  cout << "----------------------------------------------------------" << endl; 
  val = tmp; // restore original value
  fctB(&val); 
  cout << val << " at address: " << hex << &val
       << dec << " after call by pointer" << endl;
  cout << "----------------------------------------------------------" << endl; 
  val = tmp; // restore original value
  fctC(&val); 
  cout << val 
    << " at address: " << hex << &val
       << dec << " after call by pointer const"
       << " -- pointers are passed by value" << endl;
  return 0;
}
