C Structures

Lecture 16 | Unit IV: Structures and Pointers | Dr. Mohsin Dar | UPES
1 / 12

C Structures

Organizing Data Efficiently

BTech First Semester

What are Structures?

  • 📦 A collection of variables under a single name
  • 🔗 Variables can be of different data types
  • 🎯 Allows logical grouping of related data
  • 💡 Foundation for object-oriented concepts

Student Structure

Name
Age
Grade
ID

Structure Creation Process

Two Essential Steps

1️⃣

Structure Definition

Define the template

→
2️⃣

Create Variables

Use the template

Step 1: Structure Definition

General Syntax:

struct structure_name {
    data_type member1;
    data_type member2;
    // ... more members
};  // Don't forget the semicolon!

Real Example:

struct Student {
    char name[50];
    int age;
    float gpa;
    int student_id;
};

⚠️ This only creates a template - no memory allocated yet!

Step 2: Creating Structure Variables

Method 1: After Definition

struct Student student1, student2;

✓ Define structure first

✓ Create variables later

✓ More flexible approach

Method 2: During Definition

struct Student {
    char name[50];
    int age;
    float gpa;
} student1, student2;

✓ Define and create in one step

✓ Useful for one-time use

✓ More compact

Memory Allocation

name[50]
age
gpa
id

Now memory is allocated for each variable!

Accessing Structure Members

Dot Operator (.)

struct Student s1;

// Accessing members
s1.age = 20;
s1.gpa = 3.85;
strcpy(s1.name, "Alice");

Variable: s1

📝 s1.name = "Alice"

🎂 s1.age = 20

📊 s1.gpa = 3.85

🆔 s1.student_id = ?

Syntax: variable_name.member_name

Initialize Structure Members

1. Individual Assignment

struct Student s1;
s1.age = 21;
s1.gpa = 3.9;
strcpy(s1.name, "Bob");
s1.student_id = 12345;

✓ Initialize members one by one

✓ Flexible but verbose

✓ Can be done in any order

2. During Declaration

// Order must match struct definition
struct Student s1 = {
    "Charlie",  // name
    22,          // age
    3.7,         // gpa
    12345        // student_id
};

✓ Single statement initialization

✓ Must follow exact order

✓ Less flexible but concise

Copy Structure

Code Example

struct Student s1 = {"Alice", 20, 3.85, 12345};
struct Student s2;

// Copy entire structure at once!
s2 = s1;  // Copies all members

printf("s2 name: %s\n", s2.name);
// Output: Alice

✓ Single assignment copies all members

✓ Deep copy for arrays and primitives

✓ Works for nested structures too

Memory Visualization

s1 (Source)

Alice
20
3.85
→

s2 (Copy)

Alice
20
3.85

✨ Memberwise copy happens automatically!

Passing Structure to Functions

Pass by Value

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

// Call function
printStudent(s1);

✓ Creates a copy of the structure

✓ Original remains unchanged

✓ Simple but can be inefficient

Pass by Reference

void updateAge(struct Student *s, 
                      int newAge) {
    s->age = newAge;  // Arrow operator
}

// Call function
updateAge(&s1, 25);

✓ Passes memory address only

✓ Can modify original structure

✓ More efficient for large structures

💡 Best Practice: Use const with pointers when the function shouldn't modify the structure

typedef for Structures

Without typedef

// Must include 'struct' keyword
struct Student s1, s2;

// Function parameters need 'struct'
void printStudent(struct Student s);

✓ Verbose syntax

✓ Must use 'struct' keyword

✓ More typing required

With typedef

// Define the type once
typedef struct {
    char name[50];
    int age;
    float gpa;
} Student;

// Cleaner usage
Student s1, s2;
void printStudent(Student s);

✓ Clean, concise syntax

✓ No 'struct' keyword needed

✓ More maintainable code

Before typedef

struct Student s1;
→

After typedef

Student s1;

✨ typedef makes code more readable and C++-like!

Size of Structures

Structure Definition

struct Example {
    char c;     // 1 byte
    int i;      // 4 bytes
    double d;   // 8 bytes
};

printf("Size: %zu bytes\n", 
       sizeof(struct Example));
// Likely prints 16 or 24 bytes
// (not 13 bytes!)

✓ Members aligned to word boundaries

✓ Padding added for alignment

✓ Size depends on compiler and platform

Memory Layout

char c
1 byte
padding
3 bytes
int i
4 bytes
double d
8 bytes

⚠️ Total size: 16 bytes (with 4-byte alignment)

⚠️ Wasted space: 3 bytes of padding

💡 Tip: Reorder members by size (largest to smallest) to minimize padding!

Nested Structures

Structure Definitions

// Inner structure
struct Address {
    char street[100];
    char city[50];
    int zipcode;
};

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

✓ Structures can contain other structures

✓ Useful for modeling real-world data

✓ Each level needs its own dot operator

Accessing Nested Members

// Create and initialize
struct Person p1 = {
    .name = "John Doe",
    .age = 30,
    .address = {
        .street = "123 Main St",
        .city = "New York",
        .zipcode = 10001
    }
};

// Access nested members
printf("City: %s\n", p1.address.city);
strcpy(p1.address.street, "456 Park Ave");

✓ Use multiple dots to access nested members

✓ Can initialize nested structures inline

✓ Each level must be fully qualified

Person

name[50]
age
Address
street[100]
city[50]
zipcode

✨ Nested structures create a clear hierarchy in your data

Nested Structure Visualization

Person
name
age
Address
street
city
zip

Comprehensive Structure Example

Complete Program Demonstrating All Concepts

/*
 * Comprehensive example demonstrating:
 * - Structure declaration and definition
 * - Structure initialization (all methods)
 * - Nested structures
 * - Passing structures to functions
 * - Using typedef
 * - Structure size and alignment
 */

// Include necessary headers
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

// Typedef for cleaner code
typedef struct Date {
    int day;
    int month;
    int year;
} Date;

// Nested structure example
typedef struct Address {
    char street[50];
    char city[30];
    char state[20];
    int zip;
} Address;

// Main structure
typedef struct Employee {
    int id;
    char name[50];
    float salary;
    bool isActive;
    Date joinDate;      // Nested structure
    Address address;    // Nested structure
} Employee;

// Function to print employee details
void printEmployee(const Employee* emp) {
    printf("\n=== Employee Details ===\n");
    printf("ID: %d\n", emp->id);
    printf("Name: %s\n", emp->name);
    printf("Salary: $%.2f\n", emp->salary);
    printf("Status: %s\n", emp->isActive ? "Active" : "Inactive");
    printf("Join Date: %02d/%02d/%d\n", 
           emp->joinDate.day, emp->joinDate.month, emp->joinDate.year);
    printf("Address: %s, %s, %s %d\n", 
           emp->address.street, emp->address.city, 
           emp->address.state, emp->address.zip);
}

int main() {
    // Method 1: Individual assignment
    Employee emp1;
    emp1.id = 1001;
    strcpy(emp1.name, "John Doe");
    emp1.salary = 75000.0f;
    emp1.isActive = true;
    emp1.joinDate.day = 15;
    emp1.joinDate.month = 6;
    emp1.joinDate.year = 2020;
    strcpy(emp1.address.street, "123 Tech Park");
    strcpy(emp1.address.city, "Bangalore");
    strcpy(emp1.address.state, "Karnataka");
    emp1.address.zip = 560001;

    // Method 2: Designated initializer (C99+)
    Employee emp2 = {
        .id = 1002,
        .name = "Jane Smith",
        .salary = 82000.0f,
        .isActive = true,
        .joinDate = {10, 3, 2019},
        .address = {
            .street = "456 IT Park",
            .city = "Hyderabad",
            .state = "Telangana",
            .zip = 500081
        }
    };

    // Print employee details
    printEmployee(&emp1);
    printEmployee(&emp2);

    // Demonstrate structure copy
    Employee emp3 = emp1;  // Copy entire structure
    emp3.id = 1003;
    strcpy(emp3.name, "Robert Brown");
    printEmployee(&emp3);

    // Show structure size information
    printf("\n=== Structure Sizes ===\n");
    printf("Size of Date: %zu bytes\n", sizeof(Date));
    printf("Size of Address: %zu bytes\n", sizeof(Address));
    printf("Size of Employee: %zu bytes\n", sizeof(Employee));
    printf("Size of emp1: %zu bytes\n", sizeof(emp1));

    return 0;
}

Key Concepts Demonstrated:

✓ Structure declaration and definition

✓ Typedef usage

✓ Nested structures

✓ Structure initialization methods

✓ Structure assignment

✓ Passing structures to functions

✓ Structure size and padding

✓ Accessing nested members