// Our old friend ...
#include <iostream>

// This is part of the standard library, it makes std::vector available
#include <vector>

using std::cout;
using std::cin;
using std::endl;

int main ( int argc, char ** argv )
{

	//----------------------------------------------------------
	// First we look at pointers to characters.
	// This is the old (i.e., C-like) way to deal with "strings".
	// Note that main() uses this method to hand over the commandline arguments.


	// We declare name as an array of char.
	// The size of the array is automatically determined by its initializer.
	char name[] = "Saul";

	// name works like an array.  We can assign an 'P' to its first position, which has the index 0.
	name[0] = 'P';

	// Now, this is getting interesting...
	//
	// The * indicates that we are declaring a pointer.
	// Such declarations should always be read "from inside outward", i.e. right-to-left in this case.
	// Hence, name_ptr is a pointer to char.
	char * name_ptr;

	// We can assign name to name_ptr.
	// Then name_ptr will point to the first position of the char array name.
	name_ptr = name;

	for ( int i = 0; i < 4; ++i )
	{
		// We print each char of the array pointed to by name_ptr on a line for its own.
		std::cout << name_ptr[i]	<< std::endl;

		// This prints the same!
		// Here we use pointer arithmetic more directly, just to show how this works.
		// We add i to name_ptr.  The result is (name_ptr + i).
		// The we dereference this using the * operator.
		// The result is the character pointed to i positions after the start of the char array given by name_ptr.
		std::cout << *(name_ptr + i)	<< std::endl;
	}

	
	//----------------------------------------------------------
	// Next we look at pointers to double.
	

	// We declare a double zahl.  Nothing special here ;-)
	double zahl = 17;

	// Now, we declare zahl_ptr as a pointer to double.
	// (Remember to read such things from the inside outward.)
	double * zahl_ptr;
 
	// We obtain the address of zahl using the address-of operator &.
	// Then we assign the address to zahl_ptr.
	// Thus zahl_ptr will contain the address where zahl is stored in memory.
	zahl_ptr = & zahl;

	// We increment the pointer.
	++zahl_ptr;

	// Let's see what the results are.
	// The addresses are written out in hexadecimal.
	// Note that zahl_ptr is 8 larger than &zahl,
	// not 1 as one might have expected.
	// The reason is that it points to "the next double after".
	// But each double occupies 8 bytes.
	std::cout << "zahl: " << zahl <<
	         	"   zahl_ptr:" << zahl_ptr <<
	         	"   &zahl:" << &zahl <<
						std::endl;

	// We declare an array of three doubles.	
	double double_array[3];

	// Oh, we "forgot" to initialize the first position in the array.
	// It will contain unpredictable "random bits",
	// from whatever has been stored there before.
	//
	// double_array[0] = 0.001;

	double_array[1] = 1.111;  // initialize
	double_array[2] = 2.222;  // initialize

	// Quite likely, the next statement will not immediately
	// cause a crash of the program ("Segmentation violation").
	// However, we are writing to memory
	// that has not been reserved for double_array!
	// Anything might happen from this point on!
	// Unfortunately, this mistake might not become apparent until much later.
	//
	// [[[ uncomment next line to see what will happen ]]]
	// double_array[3] = 3.333; // BANG???

	// However, if the address written to is quite far away,
	// it is likely that we will get a segfault immediately
	//
	// [[[ uncomment next line to see what will happen ]]]
	// double_array[12342133] = 3.333; // BANG!!!


	//----------------------------------------------------------
	// Finally, we try out the std::vector container class.
	// In C++, you should always consider using vector instead of arrays.
	// It has many advantages.

	// Declare double_vec as a "vector of double".
	// (More on the < > syntax later.)
	std::vector<double> double_vec;

	// This makes double_vec have the desired size.
	double_vec.resize(3);

	// Note that assignment uses exactly the same syntax as for double_array.
	// This makes it easy to replace one by the other if you happen to change your mind later.
	// double_vec[0] = 0.001;
	double_vec[1] = 1.111;
	double_vec[2] = 2.222;

	// As seen for in a similar case for char* before,
	// we can assign double_array to a pointer to double.
	double * double_ptr;
	double_ptr = double_array;

	// There is not much difference between double_ptr and double_array...
	cout << "\n double_ptr: " << double_ptr <<
					"\n double_array: " << double_array << endl;

	// Now we print out the contents of the array and the vector.
	// Observe how the address of the i-th element of double_array increases.
	// Note that the contents of a vector<double> are initialized by 0
	// automatically (upon resize()), whereas this is not the case for arrays.
	// (See related remarks above.)
	for ( int i = 0; i < 3; ++i )
	{
		cout <<
				"\n &(double_array["<<i<<"]): " << &(double_array[i]) <<
				"\n double_array["<<i<<"]: " << double_array[i] <<
				"\n double_vec["<<i<<"]: " << double_vec[i] <<
			endl;
	}

	return 0;
}


