BIT102 C Programming

C ProgrammingUnit 98 min read

Structures, Unions, Enums: Data Grouping & Memory Efficiency

Unit 9 of C Programming: Explores how to bundle related data into structures, unions, and enumerations, their memory layouts, operations, and real-world uses in apps like eSewa transactions and Daraz order tracking.

TAKEAWAYS:

  • Structures group heterogeneous data under a single name, enabling logical data organization (e.g., employee records).
  • Unions share the same memory block for multiple variables, saving space but requiring careful use (e.g., storing either a phone number or email in a contact).
  • Enumerations define symbolic integer constants (e.g., enum Day {MON, TUE, WED}) for cleaner code.
  • Memory alignment and size differ between structures, unions, and arrays—critical for performance optimization.
  • Structures can be nested and passed to functions, while unions require explicit type casting.
  • Real-world examples: eSewa uses structures to store transaction details; Daraz employs enums for order statuses.

1. Introduction to Structures

A structure is a user-defined data type that groups multiple variables of different types under a single name. It allows storing related data logically.

Syntax

struct <tag> {
    <data_type> <member1>;
    <data_type> <member2>;
    ...
};
  • Tag: Optional identifier for type declaration (e.g., struct Employee).
  • Members: Variables inside the structure.

Example: Employee Record

classDiagram
    Employee : +int id
    Employee : +char name[50]
    Employee : +float salary
    Employee : +char post[20]

Declaration and Initialization

struct Employee emp1 = {101, "John", 50000.0, "Manager"};
struct Employee emp2; // Default initialization (garbage values)

Accessing Members

printf("ID: %d\n", emp1.id);
scanf("%s", emp2.name); // Note: %s for strings

Memory Layout

graph TD
    A["Memory Address"] --> B["emp1.id (int, 4 bytes)"]
    B --> C["emp1.name (char[50], 50 bytes)"]
    C --> D["emp1.salary (float, 4 bytes)"]
    D --> E["emp1.post (char[20], 20 bytes)"]

Key Points:

  • Size of a structure is the sum of its members (rounded up to the nearest multiple of the largest member’s alignment).
  • Structures can be nested:
    struct Address {
        char city[30];
        int pincode;
    };
    struct Employee {
        int id;
        char name[50];
        struct Address addr; // Nested structure
    };
    

2. Operations on Structures

(a) Input/Output

#include <stdio.h>
struct Employee {
    int id;
    char name[50];
    float salary;
};

int main() {
    struct Employee e;
    printf("Enter ID: ");
    scanf("%d", &e.id); // Use & for non-string members
    printf("Enter Name: ");
    scanf(" %[^\n]", e.name); // Read full line
    printf("Enter Salary: ");
    scanf("%f", &e.salary);
    printf("\nDetails:\nID: %d\nName: %s\nSalary: %.2f\n", e.id, e.name, e.salary);
    return 0;
}

(b) Passing Structures to Functions

void display(struct Employee e) {
    printf("ID: %d\nName: %s\n", e.id, e.name);
}

int main() {
    struct Employee e = {101, "Alice"};
    display(e); // Pass by value (copy)
    return 0;
}

Pass by Reference (Pointers):

void display(struct Employee *e) {
    printf("ID: %d\n", (*e).id); // or e->id
}

(c) Array of Structures

struct Employee emp[3] = {
    {101, "Bob", 45000},
    {102, "Charlie", 55000},
    {103, "Diana", 60000}
};

Worked Example: Filter Employees by Post

Problem: Display details of employees with post = "clerk". Solution:

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

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

int main() {
    struct Employee emp[3] = {
        {101, "Alice", "Manager", 50000},
        {102, "Bob", "Clerk", 30000},
        {103, "Charlie", "Clerk", 32000}
    };
    for (int i = 0; i < 3; i++) {
        if (strcmp(emp[i].post, "Clerk") == 0) {
            printf("ID: %d, Name: %s, Salary: %.2f\n",
                   emp[i].id, emp[i].name, emp[i].salary);
        }
    }
    return 0;
}

Output:

ID: 102, Name: Bob, Salary: 30000.00
ID: 103, Name: Charlie, Salary: 32000.00

3. Unions: Memory Efficiency at a Cost

A union shares the same memory block for all its members. Only one member can hold a value at a time.

Syntax

union Data {
    int i;
    float f;
    char str[20];
};

Memory Layout

graph TD
    A["Memory Address"] --> B["union Data (size = largest member, 20 bytes)"]
    B --> C["Member 'i' (int, 4 bytes)"]
    B --> D["Member 'f' (float, 4 bytes)"]
    B --> E["Member 'str' (char[20], 20 bytes)"]

Key Differences: Structure vs. Union

Feature Structure Union
Memory Usage Sum of all members Size of largest member
Access All members accessible Only one member active at a time
Use Case Group related data (e.g., employee) Optimize memory (e.g., flags)
Initialization All members initialized Only first member initialized

Example: Storing Contact Info

union Contact {
    long phone;
    char email[50];
};

int main() {
    union Contact c;
    c.phone = 9812345678; // Use phone
    printf("Phone: %ld\n", c.phone);
    // c.email = "test@example.com"; // Overwrites phone!
    return 0;
}

Disadvantage:

  • Data Loss: Writing to one member overwrites others.
  • No Direct Comparison: Cannot compare unions directly (use memcmp for byte comparison).

4. Enumerations (Enums): Symbolic Constants

Enums define a set of named integer constants.

Syntax

enum Day { MON, TUE, WED, THU, FRI, SAT, SUN };
  • Internally, MON = 0, TUE = 1, etc.

Example: Order Status

enum OrderStatus { PENDING, SHIPPED, DELIVERED, CANCELLED };

Usage in Functions

void printStatus(enum OrderStatus status) {
    switch (status) {
        case PENDING: printf("Order pending\n"); break;
        case SHIPPED: printf("Order shipped\n"); break;
        default: printf("Invalid status\n");
    }
}

Memory Efficiency

  • Enums occupy 1 byte (or more, depending on range) per variable.

5. Typedef for Cleaner Syntax

typedef creates aliases for complex types.

Example

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

Employee e1 = {101, "Eve"}; // No 'struct' keyword needed

6. Real-World Applications

(a) eSewa Transaction Records

  • Structure Use: Stores transaction_id, amount, timestamp, status (e.g., PENDING, COMPLETED).
  • Example:
    struct Transaction {
        int id;
        float amount;
        enum Status { PENDING, COMPLETED, FAILED } status;
    };
    

(b) Daraz Order Tracking

  • Enum Use: Tracks order status (NEW, PROCESSING, SHIPPED, DELIVERED).
  • Worked Example:
    enum OrderStatus { NEW, PROCESSING, SHIPPED, DELIVERED };
    OrderStatus status = PROCESSING;
    if (status == PROCESSING) {
        printf("Order is being processed.\n");
    }
    

(c) Pathao Driver Shift Logs

  • Union Use: Stores either distance_covered (float) or fuel_used (float) in a single memory block.
    union ShiftData {
        float distance;
        float fuel;
    };
    

7. Exam Tips

  1. Structures vs. Unions:

    • Always compare memory usage and access patterns.
    • Use structures for grouped data; unions for memory optimization.
  2. Enumerations:

    • Prefer enums over #define for symbolic constants (safer and type-checked).
    • Example: enum Color { RED, GREEN, BLUE }; instead of #define RED 1.
  3. Pointers with Structures:

    • Passing structures by pointer (struct Employee *) is efficient for large data.
    • Example:
      void updateSalary(struct Employee *e, float newSalary) {
          e->salary = newSalary;
      }
      
  4. Array of Structures:

    • Common in exams (e.g., "Store 5 student records and display names").
    • Use loops to iterate:
      for (int i = 0; i < 5; i++) {
          printf("%s\n", students[i].name);
      }
      
  5. Common Pitfalls:

    • Forgetting & for non-string members in scanf.
    • Overwriting union members without intention.
    • Not initializing structures (leads to garbage values).
  6. Code Structure:

    • Always declare structures before main().
    • Use typedef for cleaner code in larger programs.

Final Note: Structures and unions are foundational for real-world data handling. Master their memory behavior and operations to ace exams and build scalable programs!

Based on the TU BIT syllabus for C Programming (BIT102), unit 9.

Discussion

Loading…