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:
#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
#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!
#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!
#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
#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!
#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
- Create a structure for a Book with title, author, price, and year. Create an array of 3 books and print details.
- Nested structures: Create an Employee structure with nested Address. Store 5 employees and find those in a specific city.
- Dynamic allocation: Use malloc to create a Student structure, input data via pointer, and display it.