C Fundamentals

Structures in C

Learn to group related data together using simple analogies like student records and forms.

🤔 What is a Structure? (Simple Analogies)

💡 Analogy 1: Student Record Card

Imagine a school maintains information about each student. Instead of having separate lists for names, ages, and grades, they use a record card that holds everything together:

    📝 Student Record Card
    ┌─────────────────────────────────────────┐
    │  Name:        Alice Johnson             │
    │  Roll Number: 101                       │
    │  Age:         18                        │
    │  GPA:         3.8                      │
    └─────────────────────────────────────────┘
    
    This is ONE structure containing related data!
                        

🗂️ Analogy 2: The Problem Without Structures

Without structures, you'd need separate arrays for each piece of information:

    ❌ BAD: Separate Arrays (Hard to manage!)
    
    names[0] = "Alice"     ages[0] = 18      gpas[0] = 3.8
    names[1] = "Bob"       ages[1] = 19      gpas[1] = 3.5
    names[2] = "Carol"     ages[2] = 18      gpas[2] = 3.9
    
    Problem: What if we delete Alice? We need to shift ALL three arrays!
                        

With structures, everything stays together:

    ✅ GOOD: Array of Structures (Easy to manage!)
    
    students[0] = { "Alice", 18, 3.8 }  ← All data together!
    students[1] = { "Bob", 19, 3.5 }
    students[2] = { "Carol", 18, 3.9 }
                        

📋 Analogy 3: Registration Form

A structure is like a form template that defines what information to collect:

    📄 Form Template (Structure Definition)
    ┌────────────────────────────────────────┐
    │  Name: ________________  [text]        │
    │  ID:   ________________  [number]      │
    │  Age:  ________________  [number]      │
    └────────────────────────────────────────┘
    
    Each filled form is a structure variable!
                        

💻 Structure Basics in C

📐 Structure Definition Syntax

A structure groups variables of different types under one name:

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

// Structure DEFINITION (like a blueprint)
struct Student {
    char name[50];    // Member 1
    int rollNumber;   // Member 2
    float gpa;        // Member 3
};

int main() {
    // Create a structure VARIABLE
    struct Student alice;
    
    // Assign values to members
    strcpy(alice.name, "Alice");
    alice.rollNumber = 101;
    alice.gpa = 3.8;
    
    // Access and print
    printf("Name: %s\n", alice.name);
    printf("Roll: %d\n", alice.rollNumber);
    printf("GPA: %.2f\n", alice.gpa);
    
    return 0;
}

📊 Visual: Structure vs Variables

    Without Structure (Separate Variables):
    ┌───────────┐  ┌───────────┐  ┌───────────┐
    │  name     │  │   roll    │  │   gpa     │
    │ "Alice"   │  │   101     │  │   3.8     │
    └───────────┘  └───────────┘  └───────────┘
         ↑              ↑              ↑
    Different boxes, not connected!
    
    
    With Structure (Grouped Data):
    ┌─────────────────────────────────────────┐
    │         struct Student alice            │
    │  ┌─────────┐ ┌─────────┐ ┌─────────┐  │
    │  │  name   │ │  roll   │ │   gpa   │  │
    │  │"Alice"  │ │  101    │ │  3.8    │  │
    │  └─────────┘ └─────────┘ └─────────┘  │
    │     alice.name  alice.roll  alice.gpa  │
    └─────────────────────────────────────────┘
         One container, connected data!
                        

🏷️ Using typedef (Creating Aliases)

💡 Analogy: Nickname for Your Structure

Writing struct Student every time is tedious. typedef lets you create a nickname:

    typedef = "type definition" = creating a nickname
    
    Before:                    After:
    struct Student s1;    →    Student s1;
    struct Student s2;    →    Student s2;
         ↑                          ↑
    Long name                Short nickname
                        
typedef_example.c
#include <stdio.h>
#include <string.h>

// Define structure with typedef
typedef struct {
    char name[50];
    int id;
    float salary;
} Employee;  // 'Employee' is now our type name

int main() {
    // No need to write 'struct' anymore!
    Employee emp1;
    
    strcpy(emp1.name, "John");
    emp1.id = 1001;
    emp1.salary = 50000.50;
    
    printf("Employee: %s (ID: %d)\n", emp1.name, emp1.id);
    printf("Salary: $%.2f\n", emp1.salary);
    
    // Can also initialize at declaration
    Employee emp2 = {"Jane", 1002, 60000.00};
    
    return 0;
}

📚 Array of Structures (Database of Records)

💡 Analogy: Class Full of Students

Just like a real classroom has many students, each with their own record card:

    📊 Visual: Array of Students
    
    students[0]:  Alice    Roll: 101   GPA: 3.8
    students[1]:  Bob      Roll: 102   GPA: 3.5
    students[2]:  Carol    Roll: 103   GPA: 3.9
    
    Like a filing cabinet with multiple cards!
                        
array_of_structures.c
#include <stdio.h>
#include <string.h>

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

int main() {
    // Array of 3 students
    Student students[3];
    
    // Input data
    for (int i = 0; i < 3; i++) {
        printf("\nEnter student %d details:\n", i + 1);
        printf("Name: ");
        scanf(" %[^\n]", students[i].name);  // Note the space before %
        printf("Roll: ");
        scanf("%d", &students[i].roll);
        printf("Marks: ");
        scanf("%f", &students[i].marks);
    }
    
    // Display all records
    printf("\n===== STUDENT DATABASE =====\n");
    for (int i = 0; i < 3; i++) {
        printf("\nStudent %d:\n", i + 1);
        printf("Name: %s\n", students[i].name);
        printf("Roll: %d\n", students[i].roll);
        printf("Marks: %.2f\n", students[i].marks);
    }
    
    return 0;
}

🏠 Nested Structures (Structures Within Structures)

💡 Analogy: Address Inside Student Record

A student has an address, which itself has multiple parts:

    📝 Student Record with Nested Address
    ┌─────────────────────────────────────────┐
    │  Name: Alice Johnson                    │
    │  Roll: 101                              │
    │  ┌─────────────────────────────────┐   │
    │  │  Address:                        │   │
    │  │  Street: "123 Main St"          │   │
    │  │  City:   "New York"              │   │
    │  │  ZIP:    10001                   │   │
    │  └─────────────────────────────────┘   │
    └─────────────────────────────────────────┘
    
    Address is a structure INSIDE Student structure!
                        
nested_structures.c
#include <stdio.h>

typedef struct {
    char street[100];
    char city[50];
    int zipCode;
} Address;

typedef struct {
    char name[50];
    int roll;
    Address addr;  // Nested structure!
} Student;

int main() {
    Student s1 = {
        "Alice",
        101,
        {"123 Main St", "New York", 10001}  // Nested init
    };
    
    printf("Student: %s\n", s1.name);
    printf("Roll: %d\n", s1.roll);
    printf("Address: %s, %s - %d\n", 
           s1.addr.street,    // Access nested member
           s1.addr.city,      // using dot operator twice
           s1.addr.zipCode);
    
    return 0;
}

➡️ Pointers to Structures

💡 The Arrow Operator (->)

When you have a pointer to a structure, use -> instead of .:

    Structure variable:     student.name
         ↑                      ↑
    (use dot)            (member name)
    
    Structure pointer:      ptr->name
         ↑                      ↑
    (use arrow)          (member name)
    
    ptr->name is same as (*ptr).name
                        
structure_pointers.c
#include <stdio.h>
#include <stdlib.h>

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

int main() {
    // Dynamic allocation
    Item *ptr = (Item*)malloc(sizeof(Item));
    
    if (ptr == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    
    // Using arrow operator (->)
    ptr->id = 100;
    strcpy(ptr->name, "Widget");
    
    printf("Item: %s (ID: %d)\n", ptr->name, ptr->id);
    
    // Alternative: (*ptr).member
    printf("Same info: %s\n", (*ptr).name);
    
    free(ptr);
    return 0;
}

💾 Memory Layout of Structures

📐 How Structures Are Stored in Memory

    struct Student {
        char name[50];    // 50 bytes
        int roll;         // 4 bytes
        float gpa;        // 4 bytes
    };
    
    Memory Layout (conceptual):
    
    Address     Content         Size
    ┌──────┬────────────────┐
    │ 1000 │ name[0-49]     │ 50 bytes
    │ 1050 │ roll           │ 4 bytes
    │ 1054 │ gpa            │ 4 bytes
    └──────┴────────────────┘
    
    Total: 58 bytes (may include padding)
    
    Note: Actual size might be more due to alignment!
                        
sizeof_structure.c
#include <stdio.h>

typedef struct {
    char name[50];    // 50 bytes
    int roll;         // 4 bytes
    float gpa;        // 4 bytes
} Student;

int main() {
    printf("Size of Student: %zu bytes\n", sizeof(Student));
    printf("Expected: 58 bytes (50 + 4 + 4)\n");
    printf("Note: May be larger due to padding!\n");
    
    return 0;
}

⚠️ Common Mistakes with Structures

Mistake Problem Solution
Forgetting semicolon struct { } s1 struct { } s1;
Wrong access operator ptr.name vs ptr->name Use . for variable, -> for pointer
Direct assignment for strings s1.name = "Alice" Use strcpy()
Forgetting & for scanf scanf("%d", s1.roll) scanf("%d", &s1.roll)
Comparing structures if (s1 == s2) Compare members individually

📝 Practice Problems

  1. Create a structure for a Book with title, author, price, and year. Create an array of 3 books and print details.
  2. Nested structures: Create an Employee structure with nested Address. Store 5 employees and find those in a specific city.
  3. Dynamic allocation: Use malloc to create a Student structure, input data via pointer, and display it.