// Demonstrates sharing memory with union types
// Compile: gcc union1.c
// Execute: a.out
//
int main(){

    // First we look at format specifiers in printf:
    // printf stands for formatted print

    // Declare some variables
    int myInt = 3;
    float myFlt = 3.0;

    // Declare variable myUnion of union type
    // unions allow type checking rules to be violated
    // myUnion can hold an int, or a float, or an array of 4 chars
    union aUnionType{
        int i;
        float f;
        char c[4];
    } myUnion;

    // Print decimal representation of myInt
    // Format specifier %d means print the decimal representation of myInt
    printf("%d\n", myInt);    // 3

    // Now a float
    myFlt = 3.0;

    // Format specifier %f means print the float representation of myFlt
    printf("%f\n", myFlt);    // 3.0

    // Can we print myFlt as an int?
    // Yes, but we don't get 3
    printf("%d\n", myFlt);    // ???




    myUnion.i = 3;
    printf("%d\n", myUnion.i);    // 3

    // myFlt = myUnion.i;      // Type error!

    myFlt = myUnion.f;         // Type check okay

    // myUnion.i and myUnion.f are the SAME memory location
    // So myFlt contains the int 3!

    printf("%f\n", myFlt);    // ???, but not 3

    printf("%d\n", myFlt);    // This prints 3


    // Let's use the myUnion.c to examine the BYTES of myUnion.i

    myUnion.i = 1048;

    // %x means print the hexadecimal representation of 1048
    // 1048 decimal = 00 00 04 18 hexadecimal
    printf("%x\n", myUnion.i);    // 418

    // Print each byte of 1048, as a decimal
    printf("%d ", myUnion.c[0]);   // 0
    printf("%d ", myUnion.c[1]);   // 0
    printf("%d ", myUnion.c[2]);   // 4
    printf("%d\n", myUnion.c[3]);  // 24
    // 18 hexadecimal = 24 decimal

}