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