Day 9: Structures & Unions#

Overview#

Structures and unions allow us to group multiple variables of different types into a single compound data type. Today we’ll learn how to define and use them effectively.

What We’ll Learn Today#

  • Defining structures
  • Declaring structure variables
  • Accessing structure members
  • Arrays of structures
  • Nested structures
  • Pointers to structures
  • Introduction to unions
  • Comparing structures and unions

What are Structures?#

A structure is a collection of variables of different types grouped under a single name:

struct Student {
    int roll_number;
    char name[50];
    float gpa;
    char grade;
};

This defines a blueprint. To use it, we create variables:

struct Student student1;  // Create an instance

Defining Structures#

Basic Structure Definition#

struct Person {
    int age;
    float height;
    char name[50];
};

Structure Naming Convention#

  • Use descriptive names
  • Start with capital letter (e.g., struct Student)
  • Can define and declare together:
struct Student {
    int roll_number;
    char name[50];
    float gpa;
} student1, student2;  // Declare variables here too

Declaring and Initializing Structure Variables#

Declaration#

struct Student student1;  // Uninitialized

Initialization#

// Method 1: With values in order
struct Student s1 = {101, "Alice", 3.8, 'A'};

// Method 2: Partial initialization
struct Student s2 = {102, "Bob"};  // gpa and grade are 0/uninitialized

// Method 3: Zero initialization
struct Student s3 = {0};  // All members set to 0

// Method 4: Using designated initializers
struct Student s4 = {
    .roll_number = 103,
    .name = "Charlie",
    .gpa = 3.9,
    .grade = 'A'
};

Accessing Structure Members#

Use the dot operator (.) to access members:

#include <stdio.h>
#include <string.h>

struct Student {
    int roll_number;
    char name[50];
    float gpa;
    char grade;
};

int main() {
    struct Student s1 = {101, "Alice", 3.8, 'A'};

    // Access and print
    printf("Roll: %d\n", s1.roll_number);
    printf("Name: %s\n", s1.name);
    printf("GPA: %.2f\n", s1.gpa);
    printf("Grade: %c\n", s1.grade);

    // Modify members
    s1.gpa = 3.9;
    s1.grade = 'A';

    return 0;
}

Output:

Roll: 101
Name: Alice
GPA: 3.80
Grade: A

Complete Structure Program#

#include <stdio.h>
#include <string.h>

struct Employee {
    int id;
    char name[50];
    float salary;
    char department[30];
};

int main() {
    struct Employee emp1;

    // Input
    printf("Enter employee ID: ");
    scanf("%d", &emp1.id);

    printf("Enter name: ");
    scanf("%s", emp1.name);

    printf("Enter salary: ");
    scanf("%f", &emp1.salary);

    printf("Enter department: ");
    scanf("%s", emp1.department);

    // Output
    printf("\n=== Employee Information ===\n");
    printf("ID: %d\n", emp1.id);
    printf("Name: %s\n", emp1.name);
    printf("Salary: $%.2f\n", emp1.salary);
    printf("Department: %s\n", emp1.department);

    return 0;
}

Arrays of Structures#

Store multiple structure instances:

#include <stdio.h>

struct Book {
    char title[50];
    char author[50];
    float price;
};

int main() {
    // Array of 3 books
    struct Book books[3] = {
        {"C Programming", "Dennis Ritchie", 45.99},
        {"Learn C", "Yashavant Kanetkar", 39.99},
        {"The C Book", "Mike Banahan", 35.50}
    };

    // Print each book
    printf("=== Library Catalog ===\n");
    for (int i = 0; i < 3; i++) {
        printf("\nBook %d:\n", i + 1);
        printf("  Title: %s\n", books[i].title);
        printf("  Author: %s\n", books[i].author);
        printf("  Price: $%.2f\n", books[i].price);
    }

    return 0;
}

Output:

=== Library Catalog ===

Book 1:
  Title: C Programming
  Author: Dennis Ritchie
  Price: $45.99

Book 2:
  Title: Learn C
  Author: Yashavant Kanetkar
  Price: $39.99

Book 3:
  Title: The C Book
  Author: Mike Banahan
  Price: $35.50

Nested Structures#

Structures within structures:

struct Address {
    char street[50];
    char city[30];
    int zipcode;
};

struct Person {
    char name[50];
    int age;
    struct Address address;  // Nested structure
};

Accessing Nested Members#

#include <stdio.h>

struct Address {
    char street[50];
    char city[30];
    int zipcode;
};

struct Person {
    char name[50];
    struct Address address;
};

int main() {
    struct Person p1 = {
        "Alice",
        {"123 Main St", "New York", 10001}
    };

    printf("Name: %s\n", p1.name);
    printf("Street: %s\n", p1.address.street);
    printf("City: %s\n", p1.address.city);
    printf("Zipcode: %d\n", p1.address.zipcode);

    return 0;
}

Output:

Name: Alice
Street: 123 Main St
City: New York
Zipcode: 10001

Pointers to Structures#

struct Point {
    int x;
    int y;
};

// Create pointer to structure
struct Point p = {10, 20};
struct Point* ptr = &p;

Accessing Members Through Pointers#

Use the arrow operator (->):

(*ptr).x = 10;   // Method 1: Dereference then dot
ptr->x = 10;     // Method 2: Arrow operator (preferred)

Complete Example#

#include <stdio.h>

struct Point {
    int x;
    int y;
};

int main() {
    struct Point p = {10, 20};
    struct Point* ptr = &p;

    // Access through pointer
    printf("x = %d\n", ptr->x);
    printf("y = %d\n", ptr->y);

    // Modify through pointer
    ptr->x = 30;
    ptr->y = 40;

    printf("New x = %d\n", ptr->x);
    printf("New y = %d\n", ptr->y);

    return 0;
}

Structures as Function Parameters#

Pass by Value#

void printStudent(struct Student s) {
    printf("Roll: %d, Name: %s\n", s.roll_number, s.name);
}

struct Student s1 = {101, "Alice", 3.8, 'A'};
printStudent(s1);  // Entire structure copied

Pass by Reference (Better for Large Structures)#

void printStudent(struct Student* s) {
    printf("Roll: %d, Name: %s\n", s->roll_number, s->name);
}

struct Student s1 = {101, "Alice", 3.8, 'A'};
printStudent(&s1);  // Only address passed

typedef for Structures#

Simplify structure declaration using typedef:

// Without typedef
struct Student s1;

// With typedef
typedef struct {
    int roll_number;
    char name[50];
    float gpa;
} Student;

// Now use it directly
Student s1;  // Simpler!

Complete Example with typedef#

#include <stdio.h>

typedef struct {
    int id;
    char name[50];
    float salary;
} Employee;

int main() {
    Employee emp1 = {101, "Alice", 50000};
    Employee emp2 = {102, "Bob", 55000};

    printf("Employee 1: %s - $%.2f\n", emp1.name, emp1.salary);
    printf("Employee 2: %s - $%.2f\n", emp2.name, emp2.salary);

    return 0;
}

Unions#

A union is like a structure, but all members share the same memory:

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

Key Difference: Memory#

struct Structure {
    int i;        // 4 bytes
    float f;      // 4 bytes
    char c;       // 1 byte
};
// Total: ~9 bytes (possibly 12 with padding)

union Union {
    int i;        // 4 bytes
    float f;      // 4 bytes
    char c;       // 1 byte
};
// Total: 4 bytes (only the largest member)

Example#

#include <stdio.h>

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

int main() {
    union Data data;

    printf("Size of union: %lu bytes\n", sizeof(data));  // 4

    data.i = 10;
    printf("data.i = %d\n", data.i);   // 10
    printf("data.f = %f\n", data.f);   // Garbage (same memory as i)
    printf("data.c = %c\n", data.c);   // Garbage

    // Assign to f - overwrites i
    data.f = 3.14;
    printf("\nAfter assigning to f:\n");
    printf("data.i = %d\n", data.i);   // Now garbage (changed)
    printf("data.f = %f\n", data.f);   // 3.14

    return 0;
}

Output:

Size of union: 4 bytes

data.i = 10
data.f = 0.000000
data.c =

After assigning to f:
data.i = 1078557696
data.f = 3.140000

Structures vs Unions#

FeatureStructuresUnions
MemoryEach member has own spaceAll share same space
SizeSum of all membersSize of largest member
UseGroup related dataStore one of several options
ExampleStudent (name, ID, GPA)Device (keyboard, mouse, printer)

Practical Example: Student Management#

#include <stdio.h>
#include <string.h>

typedef struct {
    int roll_number;
    char name[50];
    float marks[3];
    float gpa;
} Student;

float calculateGPA(float* marks) {
    float average = (marks[0] + marks[1] + marks[2]) / 3.0;
    if (average >= 90) return 4.0;
    if (average >= 80) return 3.5;
    if (average >= 70) return 3.0;
    return 2.0;
}

int main() {
    Student students[2] = {
        {101, "Alice", {85, 90, 88}},
        {102, "Bob", {92, 88, 95}}
    };

    // Calculate and display
    for (int i = 0; i < 2; i++) {
        students[i].gpa = calculateGPA(students[i].marks);

        printf("Roll: %d, Name: %s\n", students[i].roll_number, students[i].name);
        printf("Marks: %.0f, %.0f, %.0f\n",
               students[i].marks[0],
               students[i].marks[1],
               students[i].marks[2]);
        printf("GPA: %.1f\n\n", students[i].gpa);
    }

    return 0;
}

Practice Exercises#

Exercise 1: Bookstore System#

Create a structure for books with:

  • Title, author, price, quantity
  • Create array of books
  • Display all books
  • Find most expensive book

Exercise 2: Car Dealership#

Create a structure for cars with:

  • Model, year, price, mileage
  • Use arrays to store multiple cars
  • Display inventory
  • Calculate total value

Exercise 3: Employee Records#

Create an employee structure with:

  • Name, ID, salary, address (nested structure)
  • Array of employees
  • Display all records
  • Calculate average salary

Summary#

✅ Defined and used structures
✅ Declared structure variables
✅ Accessed structure members
✅ Created arrays of structures
✅ Worked with nested structures
✅ Used pointers to structures
✅ Applied typedef for convenience
✅ Understood unions

Key Points to Remember#

  1. Structures group different data types
  2. Use . for direct access, -> for pointer access
  3. Arrays of structures allow multiple instances
  4. Pass structures by reference for efficiency
  5. typedef simplifies structure declarations
  6. Unions share memory; use when you need only one value at a time
  7. Structures are great for organizing related data

Next Steps#

Tomorrow we’ll learn about dynamic memory allocation - allocating memory at runtime!

→ Continue to Day 10

← Back to Day 8