Skip to main content

Advanced Topics

Structures and Unions

Master C Structures & Unions — what/why/applications, structure vs union, initialization, pointers, dynamic memory, passing to functions, and bit fields — using LEARNCODEGURU’s 6-level learning model.

Level 1 Basics Content

C Structures & Unions Overview

Arrays group many values of the same type. A structure groups values of different types under one name. A union looks similar but stores only one member at a time in shared memory. This level covers what they are, why structures matter, their applications, a structure vs union comparison, initialization, pointers with structures, dynamic memory for structures, passing structures to functions, and bit fields.

Topic 1

What is a structure? What is a union?

A structure is a user-defined data type that bundles related variables (called members) into a single unit. Each member gets its own memory.


struct Student {
    char  name[50];
    int   roll;
    float marks;
};                        /* semicolon is required */

struct Student s1;      /* declare a variable */
s1.roll = 101;          /* dot operator accesses members */

A union uses the same syntax but all members share one memory location. Only one member holds a valid value at any moment.


union Value {
    int   i;
    float f;
    char  c;
};

union Value v;
v.i = 65;      /* now i is valid */
v.f = 3.14;    /* now f is valid, i is garbage */
Term Meaning
Tag name The name after struct / union (e.g. Student)
Member One variable inside the structure
. (dot) Access a member of a structure variable
-> (arrow) Access a member through a pointer
Define the type → declare variables → assign members → access with . or ->
Common slip: forgetting the semicolon after the closing brace of a struct definition. It is required and produces confusing errors when missing.
Topic 2

Why structures?

  • Group related data — one Student instead of three loose variables
  • Mixed types — arrays cannot hold a string, an int, and a float together
  • Pass one argument — send an entire record to a function at once
  • Arrays of records — Student list[100]; models a whole class
  • Model the real world — the code starts describing the problem domain
  • Build data structures — linked lists, stacks, trees all need self-referential structs
  • File records — write and read a fixed-size record in one operation

/* Without a structure — three parallel arrays, easy to desynchronize */
char  names[100][50];
int   rolls[100];
float marks[100];

/* With a structure — one array of complete records */
struct Student list[100];
Topic 3

Applications of structures

# Application Example
1 Student / employee records name, id, marks, salary in one unit
2 Linked data structures Linked lists, stacks, queues, trees, graphs
3 File handling Write and read fixed-size records with fwrite / fread
4 Coordinates and geometry Point, Rectangle, Circle
5 Date and time day, month, year grouped together
6 Returning multiple values A function returns one struct instead of using several pointers
7 Bank / inventory systems Account, transaction, and product records
8 Grouping function parameters Pass one config struct instead of eight arguments

Where unions are used instead:

  • Memory-constrained systems — embedded devices where every byte counts
  • Variant / tagged types — a value that is an int or a float, never both
  • Type reinterpretation — inspecting the bytes of a value (implementation-specific)
  • Protocol messages — one of several message bodies in a fixed buffer
Topic 4

Structure vs union

# Aspect Structure Union
1 Keyword struct union
2 Memory allocated Sum of all members (plus padding) Size of the largest member only
3 Members stored Each member has its own location All members share one location
4 Valid at one time All members simultaneously Only the last one written
5 Changing one member Does not affect the others Overwrites the others
6 Initialization All members can be initialized Only one member (first, or by designator)
7 Memory efficiency Uses more memory Uses less memory
8 Typical use Records with several fields One value out of several possible types
9 Access syntax . and -> . and -> (identical)

struct S { int i; float f; char c; };   /* sizeof ~ 12 bytes */
union  U { int i; float f; char c; };   /* sizeof ~ 4 bytes  */

union U u;
u.i = 10;
u.f = 2.5;                /* u.i is now meaningless */
printf("%d\n", u.i);      /* garbage — the bytes of 2.5 read as int */
One-line answer for interviews: a structure stores all members at once and its size is the sum; a union stores one member at a time and its size is the largest.
Topic 5

Structure and union initialization

1. Positional initializer list:


struct Student s1 = { "Asha", 101, 88.5 };

2. Designated initializers (C99) — by member name:


struct Student s2 = { .roll = 102, .name = "Ravi" };
/* order does not matter; marks becomes 0 */

3. Partial initialization — the rest become zero:


struct Student s3 = { "Neha" };   /* roll = 0, marks = 0.0 */
struct Student s4 = { 0 };        /* everything zeroed */

4. Member-by-member assignment after declaration:


struct Student s5;
strcpy(s5.name, "Kiran");   /* strings need strcpy, not = */
s5.roll  = 103;
s5.marks = 91.0;

5. Copying one structure into another:


struct Student s6 = s1;   /* member-wise copy — allowed */

Union initialization — only one member:


union Value v1 = { 65 };           /* initializes the FIRST member */
union Value v2 = { .f = 3.14 };   /* designator picks another */
Strings are special: s.name = "Asha"; is invalid because you cannot assign to an array. Use strcpy(s.name, "Asha"); after declaration, or a string literal inside the initializer list.
Topic 6

Pointers with structures

A pointer to a structure uses the arrow operator -> to reach members.


struct Student s = { "Asha", 101, 88.5 };
struct Student *p = &s;

printf("%d\n", p->roll);       /* arrow — preferred */
printf("%d\n", (*p).roll);    /* same thing, parentheses required */

p->marks = 95.0;               /* changes s.marks */
You have Use Example
A structure variable Dot . s.roll
A pointer to a structure Arrow -> p->roll
A pointer, using dot Dereference first (*p).roll
Nested structure Chain them e.doj.year or p->doj.year

Self-referential structure — the basis of a linked list:


struct Node {
    int data;
    struct Node *next;   /* pointer to the same type — allowed */
};
Why not *p.roll? The dot binds tighter than *, so it parses as *(p.roll) — a compile error. Use p->roll.
Topic 7

Dynamic memory for structures

Allocating a single structure:


#include <stdlib.h>

struct Student *p = malloc(sizeof(*p));
if (p == NULL) return 1;

strcpy(p->name, "Asha");
p->roll  = 101;
p->marks = 88.5;

free(p);
p = NULL;

Allocating an array of structures:


int n, i;
scanf("%d", &n);

struct Student *list = calloc(n, sizeof(*list));
if (list == NULL) return 1;

for (i = 0; i < n; i++)
    scanf("%d", &list[i].roll);   /* list[i] is a struct → use dot */

free(list);

When the structure itself owns a pointer — free inside-out:


struct Person { char *name; int age; };

struct Person *q = malloc(sizeof(*q));
q->name = malloc(50);      /* second allocation */

free(q->name);              /* inner first */
free(q);                     /* then the struct */
Note the access rule: list[i].roll uses a dot because list[i] is a structure, while p->roll uses an arrow because p is a pointer.
Topic 8

Passing structures as function arguments

(a) By value — the function gets a copy:


void show(struct Student s) {
    printf("%s %d\n", s.name, s.roll);
    s.roll = 999;      /* changes the copy only */
}

(b) By pointer — the function can modify the original:


void promote(struct Student *s) {
    s->marks += 5;     /* changes the caller's struct */
}

promote(&s1);

(c) By const pointer — efficient and read-only:


void print(const struct Student *s) {
    printf("%s %.2f\n", s->name, s->marks);
    /* s->marks = 0;  would be a compile error */
}

(d) Returning a structure by value:


struct Point makePoint(int x, int y) {
    struct Point p;
    p.x = x;
    p.y = y;
    return p;       /* safe — the whole struct is copied out */
}
# Method Parameter Copies data? Can modify original? Best for
1 By value struct S s Yes — whole struct No Small structs, read-only
2 By pointer struct S *s No — address only Yes Modifying the caller's record
3 By const pointer const struct S *s No — address only No (enforced) Large structs, read-only
Unlike arrays, structures are not automatically passed by address. If you want the function to change the original, you must pass &s explicitly.
Topic 9

Bit fields

A bit field lets a structure member occupy an exact number of bits instead of a whole integer — useful when memory is tight or when modelling flags.


struct Flags {
    unsigned int isActive : 1;   /* 1 bit  → 0 or 1   */
    unsigned int isAdmin  : 1;   /* 1 bit             */
    unsigned int level    : 4;   /* 4 bits → 0 to 15  */
};

struct Flags f = { 0 };
f.isActive = 1;
f.level    = 12;

printf("size = %zu\n", sizeof(f));  /* often 4, not 12 */
Rule Detail
Syntax type name : width;
Allowed types int, unsigned int, signed int, _Bool
Value range n bits unsigned holds 0 .. 2^n − 1
Address-of Not allowed — &f.level is illegal
Arrays of bit fields Not allowed
Unnamed field unsigned : 3; reserves padding bits
Zero-width field unsigned : 0; forces the next field to a new storage unit
Memory layout Implementation-defined — not portable
Warning: use bit fields to save memory inside your own program, not to map hardware registers or file formats. Bit ordering and packing vary between compilers.
Example

Sample program — structure, pointer, union, and bit field


/* Structures and unions in one program */
#include <stdio.h>
#include <string.h>

struct Student {
    char  name[50];
    int   roll;
    float marks;
};

union Value {
    int   i;
    float f;
};

struct Flags {
    unsigned int passed : 1;
    unsigned int grade  : 3;
};

void print(const struct Student *s);

int main(void) {
    struct Student s = { "Asha", 101, 88.5 };
    struct Student *p = &s;
    union Value v;
    struct Flags f = { 0 };

    print(p);

    p->marks = 92.0;              /* modify through the pointer */
    printf("updated marks: %.2f\n", s.marks);

    v.i = 10;
    printf("union as int: %d\n", v.i);
    v.f = 2.5;                  /* overwrites the same bytes */
    printf("union as float: %.2f\n", v.f);

    f.passed = 1;
    f.grade  = 5;
    printf("passed=%u grade=%u size=%zu\n",
           f.passed, f.grade, sizeof(f));

    printf("sizeof struct = %zu, sizeof union = %zu\n",
           sizeof(struct Student), sizeof(union Value));

    return 0;
}

void print(const struct Student *s) {
    printf("%s (%d) : %.2f\n", s->name, s->roll, s->marks);
}
What to observe: the dot on variables, the arrow on pointers, the union overwriting its own bytes, and how much smaller the bit-field structure is than three separate integers.

Level 2 Advanced Content

Going deeper into structures and unions

Level 1 covered definitions, comparison, initialization, pointers, dynamic memory, function passing, and bit fields. Level 2 explains typedef, nested structures, arrays of structures, padding and alignment, shallow vs deep copy, tagged unions, self-referential structures, and common mistakes.

Topic 1

typedef — cleaner declarations


/* Without typedef */
struct Point { int x, y; };
struct Point p1;          /* must repeat 'struct' */

/* With typedef */
typedef struct {
    int x, y;
} Point;

Point p2;                  /* clean */

/* Both tag and typedef — needed for self-reference */
typedef struct Node {
    int data;
    struct Node *next;    /* typedef name not ready yet here */
} Node;
Topic 2

Nested structures and arrays of structures


struct Date {
    int day, month, year;
};

struct Employee {
    char name[50];
    struct Date doj;      /* nested structure */
    float salary;
};

struct Employee e = { "Ravi", { 15, 8, 2020 }, 55000 };

printf("%d\n", e.doj.year);   /* chain the dots */

/* Array of structures */
struct Student list[3] = {
    { "Asha", 101, 88.5 },
    { "Ravi", 102, 76.0 },
    { "Neha", 103, 91.5 }
};

for (i = 0; i < 3; i++)
    printf("%s %d\n", list[i].name, list[i].roll);
Topic 3

Padding, alignment, and sizeof

The compiler inserts padding bytes so each member starts at an address suitable for its type. That is why sizeof often exceeds the sum of the members.

Definition Sum of members Typical sizeof Why
struct { char c; int i; } 5 8 3 padding bytes before i
struct { int i; char c; } 5 8 3 trailing bytes for array alignment
struct { char a; int i; char b; } 6 12 Padding around i
struct { int i; char a, b; } 6 8 Better ordering — less padding
Ordering members from largest to smallest usually minimizes padding. This matters when you allocate arrays of thousands of records.
Topic 4

Shallow copy vs deep copy


struct Person { char *name; int age; };

struct Person a, b;
a.name = malloc(50);
strcpy(a.name, "Asha");

b = a;               /* SHALLOW: both point at the SAME buffer */
strcpy(b.name, "Ravi");  /* a.name also becomes "Ravi" */

/* DEEP copy — allocate separate storage */
b.name = malloc(50);
strcpy(b.name, a.name);
  • = on structures copies members, including pointer values
  • Two shallow copies sharing a buffer means a double free risk
  • Deep copy means allocating new memory for every pointer member
Topic 5

Tagged unions — the safe way to use a union

A union alone cannot tell you which member is valid. Wrap it in a structure with a tag that records the current type.


enum Kind { KIND_INT, KIND_FLOAT, KIND_CHAR };

struct Variant {
    enum Kind kind;        /* which member is valid */
    union {
        int   i;
        float f;
        char  c;
    } value;
};

void show(const struct Variant *v) {
    switch (v->kind) {
        case KIND_INT:   printf("%d\n", v->value.i); break;
        case KIND_FLOAT: printf("%f\n", v->value.f); break;
        case KIND_CHAR:  printf("%c\n", v->value.c); break;
    }
}
Always set the tag whenever you write a union member. Reading a member other than the last one written is how union bugs begin.
Topic 6

Self-referential structures — a linked list node


struct Node {
    int data;
    struct Node *next;
};

/* Build two linked nodes on the heap */
struct Node *head = malloc(sizeof(*head));
head->data = 10;
head->next = malloc(sizeof(*head));
head->next->data = 20;
head->next->next = NULL;   /* end of list */

/* Free every node before exiting */
free(head->next);
free(head);
A structure may contain a pointer to its own type, but never an instance of itself — that would require infinite size.
Topic 7

Common mistakes

Mistake Why it hurts Fix
Missing ; after the closing brace Confusing cascade of syntax errors }; ends every struct definition
Using . on a pointer Compile error Use -> or (*p).member
s.name = "Asha"; Cannot assign to an array strcpy(s.name, "Asha");
Comparing structs with == Not allowed in C Compare member by member
Reading the wrong union member Reinterprets unrelated bytes Track the active member with a tag
Expecting the sum of members from sizeof Ignores padding Trust sizeof, reorder to shrink
Passing a large struct by value Expensive full copy Pass const struct T *
Shallow copy of a struct owning a pointer Shared buffer, double free Deep copy each pointer member
Freeing the struct before its inner pointers Leaks the inner allocations Free inside-out
Taking & of a bit field Illegal — no guaranteed address Copy into a normal variable first

Level 3 C Tricky Interview Points

Advanced tricky interview points on structure vs union memory, padding, assignment vs comparison, arrow syntax, self-reference, passing conventions, and bit fields.

Tricky Interview Point-1:

A structure allocates space for every member; a union allocates only the largest

sizeof(struct) is at least the sum of members plus padding. sizeof(union) equals the size of its largest member (rounded for alignment). This single sentence answers most structure-vs-union questions.

Tricky Interview Point-2:

All union members share the same memory — writing one corrupts the others

Only the most recently written member holds a meaningful value. Reading a different member reinterprets the same bytes, which is why unions need a separate "tag" field to track what is currently stored.

Tricky Interview Point-3:

sizeof(struct) is usually larger than the sum of its members — padding

Compilers insert padding so each member sits at a properly aligned address. struct { char c; int i; } is typically 8 bytes, not 5. Reordering members largest-to-smallest often shrinks the struct.

Tricky Interview Point-4:

Structures cannot be compared with == , even if all members match

There is no built-in structure comparison because padding bytes are indeterminate. Compare member by member, or use memcmp only when you know the padding was zeroed.

Tricky Interview Point-5:

Structures CAN be assigned and copied with = , unlike arrays

s2 = s1; performs a member-wise copy. This is a shallow copy — pointer members are duplicated as addresses, so both structures then point at the same data.

Tricky Interview Point-6:

p->member is shorthand for (*p).member — and the parentheses matter

*p.member parses as *(p.member) because . binds tighter than *. That is a compile error for a pointer. Always use -> or write (*p).member explicitly.

Tricky Interview Point-7:

A structure cannot contain itself, but it can contain a pointer to itself

struct Node { struct Node next; }; is impossible (infinite size). struct Node { struct Node *next; }; is fine and is the foundation of linked lists and trees.

Tricky Interview Point-8:

Passing a structure by value copies the whole thing

For large structures this is expensive. Pass const struct T *p instead: the function gets an address (cheap) and const documents that it will not modify the original.

Tricky Interview Point-9:

Designated initializers let you initialize members by name (C99)

struct Point p = { .y = 5, .x = 3 }; is order-independent and self-documenting. Unlisted members are zero-initialized, which is safer than positional lists when a struct grows.

Tricky Interview Point-10:

Only the first member of a union can be initialized without designators

union U u = { 10 }; initializes the first member. To set another, use a designator: union U u = { .f = 3.14 };. Attempting to initialize two members at once is an error.

Tricky Interview Point-11:

typedef removes the need to write struct every time

typedef struct { int x, y; } Point; lets you declare Point p; instead of struct Point p;. The tag name and typedef name are in different namespaces, so both can be the same word.

Tricky Interview Point-12:

Bit fields have no defined memory layout or bit order

Whether bits pack left-to-right or right-to-left, and how they straddle storage units, is implementation-defined. Never use bit fields to parse a hardware register or file format portably.

Tricky Interview Point-13:

You cannot take the address of a bit field

&s.flag is illegal because a bit field may not start at a byte boundary. They also cannot be members of arrays and are restricted to integer types.

Tricky Interview Point-14:

An unnamed bit field of width 0 forces alignment to the next storage unit

unsigned : 0; is a special directive that starts the next field at a fresh boundary. An unnamed field with a nonzero width simply reserves padding bits you cannot access.

Tricky Interview Point-15:

A flexible array member must be last and needs a matching malloc

struct S { int n; int data[]; }; is allocated with malloc(sizeof(struct S) + n * sizeof(int)). It lets one allocation hold both the header and a variable-length payload.

Interview tip: when asked about structures, mention size and padding, copy semantics (assignable but not comparable), and how you pass them. Those three cover most follow-up questions.

Level 4 Simple Programs

Short programs covering records, arrays of structures, function passing, dynamic allocation, unions, and bit fields.

Program 1 — Student record: read and print


/* Basic structure input and output */
#include <stdio.h>

struct Student {
    char  name[50];
    int   roll;
    float marks;
};

int main(void) {
    struct Student s;

    printf("Enter name, roll, marks: ");
    scanf("%49s %d %f", s.name, &s.roll, &s.marks);

    printf("\nName  : %s\n", s.name);
    printf("Roll  : %d\n", s.roll);
    printf("Marks : %.2f\n", s.marks);

    return 0;
}

Program 2 — Array of structures: find the topper


/* n records, then the highest marks */
#include <stdio.h>

struct Student {
    char  name[50];
    int   roll;
    float marks;
};

int main(void) {
    struct Student list[50];
    int n, i, best = 0;

    printf("How many students? ");
    scanf("%d", &n);

    for (i = 0; i < n; i++) {
        printf("Student %d (name roll marks): ", i + 1);
        scanf("%49s %d %f",
              list[i].name, &list[i].roll, &list[i].marks);
    }

    for (i = 1; i < n; i++)
        if (list[i].marks > list[best].marks)
            best = i;

    printf("\nTopper: %s (%d) with %.2f\n",
           list[best].name, list[best].roll, list[best].marks);

    return 0;
}

Program 3 — Passing a structure by value and by pointer


/* Only the pointer version changes the original */
#include <stdio.h>

typedef struct {
    int roll;
    float marks;
} Student;

void byValue(Student s);
void byPointer(Student *s);
void show(const Student *s);

int main(void) {
    Student s = { 101, 80.0 };

    byValue(s);
    printf("after byValue:   ");
    show(&s);

    byPointer(&s);
    printf("after byPointer: ");
    show(&s);

    return 0;
}

void byValue(Student s) {
    s.marks += 10;      /* local copy only */
}

void byPointer(Student *s) {
    s->marks += 10;     /* the real record */
}

void show(const Student *s) {
    printf("roll=%d marks=%.2f\n", s->roll, s->marks);
}

Program 4 — Dynamic array of structures


/* calloc an array of records, then free it */
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    char name[50];
    int  roll;
} Student;

int main(void) {
    Student *list;
    int n, i;

    printf("How many students? ");
    scanf("%d", &n);

    list = calloc(n, sizeof(*list));
    if (list == NULL) {
        printf("Out of memory\n");
        return 1;
    }

    for (i = 0; i < n; i++) {
        printf("Name and roll: ");
        scanf("%49s %d", list[i].name, &list[i].roll);
    }

    printf("\nRecords:\n");
    for (i = 0; i < n; i++)
        printf("%-10s %d\n", list[i].name, list[i].roll);

    free(list);
    list = NULL;

    return 0;
}

Program 5 — Union behaviour and size comparison


/* Shared memory in action */
#include <stdio.h>

struct S { int i; float f; char c; };
union  U { int i; float f; char c; };

int main(void) {
    struct S s;
    union U u;

    s.i = 10;
    s.f = 2.5;
    s.c = 'A';
    printf("struct: i=%d f=%.1f c=%c\n", s.i, s.f, s.c);

    u.i = 10;
    printf("union after u.i = 10 : %d\n", u.i);
    u.f = 2.5;
    printf("union after u.f = 2.5: i is now %d\n", u.i);

    printf("\nsizeof struct = %zu\n", sizeof(struct S));
    printf("sizeof union  = %zu\n", sizeof(union U));

    return 0;
}

Program 6 — Bit fields for flags


/* Pack several small values into a few bytes */
#include <stdio.h>

struct Packed {
    unsigned int isActive : 1;
    unsigned int isAdmin  : 1;
    unsigned int level    : 4;
    unsigned int zone     : 6;
};

struct Plain {
    unsigned int isActive, isAdmin, level, zone;
};

int main(void) {
    struct Packed p = { 0 };

    p.isActive = 1;
    p.level    = 12;      /* fits in 4 bits (max 15) */
    p.zone     = 40;      /* fits in 6 bits (max 63) */

    printf("active=%u level=%u zone=%u\n",
           p.isActive, p.level, p.zone);

    printf("packed size = %zu\n", sizeof(struct Packed));
    printf("plain  size = %zu\n", sizeof(struct Plain));

    return 0;
}
Comment Directive Type Keyword Function Variable String Number

Level 5 Problem Solving Tricks

How to master structures and unions while solving problems

Most structure bugs come from mixing up . and ->, assigning to array members, copying structures that own pointers, and reading the wrong union member. These habits keep record-based code clean.

Trick 1

Use typedef so declarations read like the domain

typedef struct { char name[50]; int roll; float marks; } Student; then write Student s; The code starts describing the problem instead of the language.

Trick 2

Pass const pointers for read-only structures

void print(const Student *s) avoids a full copy and tells both the compiler and the reader that nothing will be modified. Use a plain pointer only when you intend to change the struct.

Trick 3

Always use -> when you have a pointer

If the variable is a pointer, reach for ->. If it is a struct value, use the dot. Deciding this from the declaration, not by trial and error, eliminates a whole class of compile errors.

Trick 4

Give unions a tag field to know what is stored

struct { int kind; union { int i; float f; } value; } is the standard "tagged union" pattern. Without the tag you have no safe way to know which member is currently valid.

Trick 5

Use designated initializers for structs with many members

Point p = { .x = 3, .y = 5 }; survives reordering and additions to the struct, while a positional list silently assigns to the wrong members when the definition changes.

Trick 6

Order members largest to smallest to reduce padding

Placing double, then int, then char usually produces a smaller structure than the reverse. Check with sizeof if memory matters, especially for arrays of thousands of structs.

Trick 7

For arrays of structs, allocate with calloc

Student *list = calloc(n, sizeof(*list)); gives you n zeroed records in one call, so numeric fields start at 0 and strings start empty without an initialization loop.

Trick 8

Free nested pointers before freeing the structure

If a struct owns a malloc'd name field, free(s->name) first, then free(s). Freeing the struct first loses the inner address and leaks it.

Quick success checklist

  • Before run: semicolon after the definition? strcpy for strings? dot vs arrow correct?
  • Debug order: print each member → check sizeof → verify which union member is active
  • Memory habit: pass large structs by const pointer → deep copy pointer members → free inside-out
Level-5 goal: model the data first, choose structure or union by whether members coexist, and always know whether you are holding a record or a pointer to one.

Level 6 Practice Programs List

Programming questions only — focused on structures and unions: records, initialization, pointers, dynamic memory, function passing, unions, and bit fields.

  1. 1. Write a C program that defines a structure Student with name, roll number, and marks; reads one student; and prints the details.
  2. 2. Write a C program that reads n students into an array of structures and prints the one with the highest marks.
  3. 3. Write a C program that defines a structure and initializes it three ways: positional list, designated initializers, and member assignment.
  4. 4. Write a C program that uses a pointer to a structure and accesses all members with the -> operator.
  5. 5. Write a C program that passes a structure to a function by value and by pointer, and shows which one can modify the original.
  6. 6. Write a C program that returns a structure from a function (for example, a function that builds a Point from two integers).
  7. 7. Write a C program that allocates a single structure with malloc, fills it, prints it, and frees it.
  8. 8. Write a C program that allocates an array of n structures dynamically with calloc, reads them, and frees the memory.
  9. 9. Write a C program that defines a union with an int, a float, and a char array, and prints sizeof for the union and an equivalent structure.
  10. 10. Write a C program that demonstrates that writing one union member changes the value read from another.
  11. 11. Write a C program that uses a bit field structure to store several 1-bit flags and prints sizeof the structure.
  12. 12. Write a C program that defines a nested structure (for example, Employee containing a Date of joining) and prints all fields.