#include <stdio.h>
#include <stdlib.h>

// you can compile this with gcc -o pointers.exe pointers.c
// on windows

// or

// gcc -o pointers pointers.c 
// on linux

struct _test
{
    int a, b, c;
};

typedef struct _test test;

void printtest(test itest)
{
    printf("itest.a = %d\n",itest.a);
    printf("itest.b = %d\n",itest.b);
    printf("itest.c = %d\n",itest.c);
}

void printtestptr(test* itest)
{
    printf("*itest.a = %d\n",itest -> a);
    printf("*itest.b = %d\n",itest -> b);
    printf("*itest.c = %d\n",itest -> c);
}

int main ()
{
  test test1;

  test1.a = 1;
  test1.b = 2;
  test1.c = 3;

  // works because we're sending the whole structure to the function,
  // this function is expecting to be passed data of type test
  printtest(test1);

  test1.a = 11;
  test1.b = 12;
  test1.c = 13;

  // works because we're sending the ADDRESS of a structure of type test
  // it dereferences that address internally
  printtestptr(&test1);



// NO
/*
  printtestptr(test1);
  // sending a statically defined value to something expecting an address.
  // instead of a 64 bit address, it gets some big mess.

  printtestptr(*test1);
  // *StaticVariable means "find the value pointed to by this chunk of memory",
  // meaningless in this case since test1 is a struct.
*/

  test* test2 = malloc(sizeof(test));

// NO
/*
    test* test2;
    // without malloc we are assigning values to areas we haven't allocated.
    // declaring a pointer STORAGE AREA allocates memory FOR THE POINTER (~64 bits),
    // NOT what it points to (something that can be much larger than 64 bits).
*/

  test2 -> a = 21;
  test2 -> b = 22;
  test2 -> c = 23;

    // below works because we dereference (get the value at address test2) the address before sending it
  printtest(*test2);

  test2 -> a = 31;
  test2 -> b = 32;
  test2 -> c = 33;

    // below works because we're giving it an address which it dereferences internally
  printtestptr(test2);

// NO
/*
    //C/C++ type checks!

  printtest(test2);
  // printtest will try to read in this pointer (64 bits) as a structure, and well that doesn't work...
  // it doesn't have the same structure

  printtestptr(*test2)
  // printtestptr will try to read the structure as an address. Won't have the right structure.
*/

  return 0;
}
