// Demonstrates a structure type,
//    a composite structure type, and
//    an array of structures
// Demonstrates reference vs value semantics

// Compile: gcc strucarray.c
// Execute: a.out

#include <stdio.h>
int main(){

    struct Pair {int x; int y;};  // Declare type Pair (semi after }!)

    struct Pair pair1, pair2, pair3;    // Declare three Pairs

    // Demonstrate access the fields of the struct
    pair1.x = 1;
    pair1.y = 2;
    pair2.x = 3;
    pair2.y = 4;

    // Output the pairs, line, and array
    printf("pair1 = (%d, %d)\n", pair1.x, pair1.y);  // pair1 = (1, 2)
    printf("pair2 = (%d, %d)\n", pair2.x, pair2.y);  // pair2 = (3, 4)

    // //////////////////////////////////////////////////////
    const int size = 3;    // int const size = 3 also works
    struct Pair a[size];   // Array of Pairs

    // Read in values for part of the array
    int i, n;
    for (i = 0; i < size; i++){
        scanf("%d", &n);   // get(n);
        a[i].x = n;
        scanf("%d", &a[i].y);   // get(a[i].y);
    }

    for (i=0; i<size; i++){
        printf("i and a[i] = %d and (%d, %d)\n", i, a[i].x, a[i].y);
    }
    //  i and a[i] = 0 and (11, 12)
    //  i and a[i] = 1 and (13, 14)
    //  i and a[i] = 2 and (15, 16)


    // //////////////////////////////////////////////////////
    // A Line is a nested record
    // Typedef defines Line_t as a new name for this type

    typedef struct Line {struct Pair p1; struct Pair p2;} Line_t;

    Line_t l;   //  Declare a Line_t

    // Now assign the fields of the nested record
    l.p1 = pair1;
    l.p2 = pair2;

    printf("l.p1 = (%d, %d)\n", l.p1.x, l.p1.y);  // l.p1 = (1, 2)
    printf("l.p2 = (%d, %d)\n", l.p2.x, l.p2.y);  // l.p2 = (3, 4)

    // Check for reference vs value semantics
    pair1.x = 99;
    printf("l.p1 = (%d, %d)\n", l.p1.x, l.p1.y);  // l.p1 = (1, 2)


    // //////////////////////////////////////////////////////
    // Check reference vs value semantics for assigning pairs
    pair3 = pair2;
    pair2.y = 22;    // Will this change pair3?
    printf("pair2 = (%d, %d)\n", pair2.x, pair2.y);   // pair2 = (3, 22)
    printf("pair3 = (%d, %d)\n", pair3.x, pair3.y);   // pair3 = (3, 4)
    

    // What about an equality test?
    printf("0 is false, nonzero is true:  %d\n", pair2.y == pair3.y);
    //  0 is false, nonzero is true:  0
    
    // Can we do a direct comparison, like this:
    // printf("0 is false, nonzero is true:  %d\n", pair2 == pair3);
    // No. Can't compare records, only their fields.
    

    // Check reference vs value semantics for nested records
    pair3 = l.p2;
    l.p2.x = 33;  // Will this change pair3?
    printf("pair3 = (%d, %d)\n", pair3.x, pair3.y);  // pair3 = (3, 4)
    printf("l.p2 = (%d, %d)\n", l.p2.x, l.p2.y);     // l.p2 = (33, 4)

    // Reassign the first array element directly
    a[0] = pair2;
    pair2.y = 44;    // Will this change a[0]?
    printf("pair2 = (%d, %d)\n", pair2.x, pair2.y);  //  pair2 = (3, 44)
    printf("a[0] = (%d, %d)\n", a[0].x, a[0].y);     // a[0] = (3, 22)
}