DevAcademia
C++C#CPythonJava
  • C Basics

  • Introduction to C
  • Getting Started with C
  • C Syntax
  • C Output
  • C Comments
  • C Variables
  • C Data Types
  • C Constants
  • C Operators
  • C Booleans
  • C If...Else Statements
  • C Switch Statement
  • C While Loops
  • C For Loops
  • C Break and Continue
  • C Strings
  • C User Input
  • C Memory Address
  • C Pointers
  • C Files
  • C Functions

  • C Functions
  • C Function Parameters
  • C Scope
  • C Function Declaration
  • C Recursion
  • C Math Functions
  • C Structures

  • C Structures
  • C Structs & Pointers
  • C Unions
  • C Enums

  • C Enums
  • C Memory

  • C Allocate Memory
  • C Access Memory
  • C Reallocate Memory
  • C Deallocate Memory
  • C Structs and Memory
  • C Memory Example
  • C Quiz

  • C Quiz
  • C Basics

  • Introduction to C
  • Getting Started with C
  • C Syntax
  • C Output
  • C Comments
  • C Variables
  • C Data Types
  • C Constants
  • C Operators
  • C Booleans
  • C If...Else Statements
  • C Switch Statement
  • C While Loops
  • C For Loops
  • C Break and Continue
  • C Strings
  • C User Input
  • C Memory Address
  • C Pointers
  • C Files
  • C Functions

  • C Functions
  • C Function Parameters
  • C Scope
  • C Function Declaration
  • C Recursion
  • C Math Functions
  • C Structures

  • C Structures
  • C Structs & Pointers
  • C Unions
  • C Enums

  • C Enums
  • C Memory

  • C Allocate Memory
  • C Access Memory
  • C Reallocate Memory
  • C Deallocate Memory
  • C Structs and Memory
  • C Memory Example
  • C Quiz

  • C Quiz

Loading C tutorial…

Loading content
C MemoryTopic 62 of 64
←PreviousPrevNextNext→

C Structs and Memory

Introduction to Structures and Memory

Structures (structs) in C are user-defined data types that allow you to group related variables of different types under a single name. Understanding how structs interact with memory is crucial for effective C programming, especially when dealing with dynamic memory allocation, memory layout, and performance optimization.

Key concepts for structs and memory:

- Memory layout and alignment of struct members

- Dynamic allocation of structs

- Arrays of structs and struct pointers

- Memory padding and struct packing

- Passing structs to functions efficiently

Basic Struct Declaration and Memory Layout

Example
#include <stdio.h>

struct Person {
    char name[50];
    int age;
    float height;
    double salary;
};

int main(void) {
    struct Person person1;
    
    printf("Size of struct Person: %zu bytes\n", sizeof(struct Person));
    printf("Size of name: %zu bytes\n", sizeof(person1.name));
    printf("Size of age: %zu bytes\n", sizeof(person1.age));
    printf("Size of height: %zu bytes\n", sizeof(person1.height));
    printf("Size of salary: %zu bytes\n", sizeof(person1.salary));
    
    printf("\nMemory layout:\n");
    printf("Address of person1: %p\n", (void*)&person1);
    printf("Address of name: %p\n", (void*)&person1.name);
    printf("Address of age: %p\n", (void*)&person1.age);
    printf("Address of height: %p\n", (void*)&person1.height);
    printf("Address of salary: %p\n", (void*)&person1.salary);
    
    return 0;
}
Output
Size of struct Person: 72 bytes
Size of name: 50 bytes
Size of age: 4 bytes
Size of height: 4 bytes
Size of salary: 8 bytes

Memory layout:
Address of person1: 0x7fff5fbff5a0
Address of name: 0x7fff5fbff5a0
Address of age: 0x7fff5fbff5d4
Address of height: 0x7fff5fbff5d8
Address of salary: 0x7fff5fbff5e0
ℹ️ Note: The total struct size (72 bytes) is larger than the sum of individual members (66 bytes) due to memory padding for alignment. Exact sizes and addresses are implementation/ABI dependent.

Memory Padding and Alignment

⚠️ Warning: Ordering struct members poorly can waste memory due to padding. Arrange members from largest to smallest for better efficiency. Sizes/offsets may vary by platform.
Example
#include <stdio.h>
#include <stddef.h>

struct Example1 {
    char a;
    int b;
    char c;
    double d;
};

struct Example2 {
    double d;
    int b;
    char a;
    char c;
};

int main(void) {
    printf("Struct with padding:\n");
    printf("Size of Example1: %zu bytes\n", sizeof(struct Example1));
    printf("Offset of a: %zu\n", offsetof(struct Example1, a));
    printf("Offset of b: %zu\n", offsetof(struct Example1, b));
    printf("Offset of c: %zu\n", offsetof(struct Example1, c));
    printf("Offset of d: %zu\n", offsetof(struct Example1, d));
    
    printf("\nOptimized struct layout:\n");
    printf("Size of Example2: %zu bytes\n", sizeof(struct Example2));
    printf("Offset of d: %zu\n", offsetof(struct Example2, d));
    printf("Offset of b: %zu\n", offsetof(struct Example2, b));
    printf("Offset of a: %zu\n", offsetof(struct Example2, a));
    printf("Offset of c: %zu\n", offsetof(struct Example2, c));
    
    return 0;
}
Output
Struct with padding:
Size of Example1: 24 bytes
Offset of a: 0
Offset of b: 4
Offset of c: 8
Offset of d: 16

Optimized struct layout:
Size of Example2: 16 bytes
Offset of d: 0
Offset of b: 8
Offset of a: 12
Offset of c: 13

Dynamic Memory Allocation for Structs

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

struct Student {
    char name[30];
    int id;
    float gpa;
};

int main(void) {
    struct Student *student = malloc(sizeof *student);
    if (student == NULL) return 1;

    strcpy(student->name, "John Doe");
    student->id = 12345;
    student->gpa = 3.85;

    printf("Student Information:\n");
    printf("Name: %s\n", student->name);
    printf("ID: %d\n", student->id);
    printf("GPA: %.2f\n", student->gpa);

    int numStudents = 3;
    struct Student *students = malloc((size_t)numStudents * sizeof *students);
    if (students == NULL) {
        free(student);
        return 1;
    }

    strcpy(students[0].name, "Alice Smith"); students[0].id = 11111; students[0].gpa = 3.9f;
    strcpy(students[1].name, "Bob Johnson"); students[1].id = 22222; students[1].gpa = 3.7f;
    strcpy(students[2].name, "Carol Davis"); students[2].id = 33333; students[2].gpa = 3.8f;

    printf("\nStudent Array:\n");
    for (int i = 0; i < numStudents; i++) {
        printf("%s (ID: %d, GPA: %.2f)\n", students[i].name, students[i].id, students[i].gpa);
    }

    free(student);
    free(students);
    return 0;
}
Output
Student Information:
Name: John Doe
ID: 12345
GPA: 3.85

Student Array:
Alice Smith (ID: 11111, GPA: 3.90)
Bob Johnson (ID: 22222, GPA: 3.70)
Carol Davis (ID: 33333, GPA: 3.80)

Structs with Dynamic Members

⚠️ Warning: When structs contain dynamic members, free the members before freeing the struct itself.
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct DynamicString {
    char *text;
    int length;
    int capacity;
};

struct DynamicString* createString(const char *initial) {
    struct DynamicString *str = malloc(sizeof *str);
    if (!str) return NULL;

    size_t len = strlen(initial);
    str->length = (int)len;
    str->capacity = (int)len + 1 + 10; // extra space plus terminator
    str->text = malloc((size_t)str->capacity);
    if (!str->text) { free(str); return NULL; }

    strcpy(str->text, initial);
    return str;
}

void freeString(struct DynamicString *str) {
    if (str) {
        free(str->text);
        free(str);
    }
}

int main(void) {
    struct DynamicString *myStr = createString("Hello, World!");
    if (!myStr) return 1;

    printf("Text: %s\nLength: %d\nCapacity: %d\n", myStr->text, myStr->length, myStr->capacity);

    freeString(myStr);
    return 0;
}
Output
Text: Hello, World!
Length: 13
Capacity: 24

Passing Structs to Functions

Example
#include <stdio.h>

struct Point { double x, y; };

void printPointByValue(struct Point p) {
    printf("Point (by value): (%.2f, %.2f)\n", p.x, p.y);
}

void printPointByPointer(const struct Point *p) {
    printf("Point (by pointer): (%.2f, %.2f)\n", p->x, p->y);
}

void movePoint(struct Point *p, double dx, double dy) {
    p->x += dx;
    p->y += dy;
}

int main(void) {
    struct Point p1 = {3.0, 4.0};

    printPointByValue(p1);
    printPointByPointer(&p1);
    movePoint(&p1, 1.0, -1.0);
    printf("After move: (%.2f, %.2f)\n", p1.x, p1.y);

    return 0;
}
Output
Point (by value): (3.00, 4.00)
Point (by pointer): (3.00, 4.00)
After move: (4.00, 3.00)

Memory Management Best Practices

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

struct Employee {
    char *name;
    int *scores;
    int numScores;
};

struct Employee* createEmployee(const char *name, int numScores) {
    struct Employee *emp = malloc(sizeof *emp);
    if (!emp) return NULL;

    emp->name = malloc(strlen(name) + 1);
    if (!emp->name) { free(emp); return NULL; }
    strcpy(emp->name, name);

    if (numScores > 0) {
        emp->scores = calloc((size_t)numScores, sizeof *emp->scores);
        if (!emp->scores) { free(emp->name); free(emp); return NULL; }
        emp->numScores = numScores;
    } else {
        emp->scores = NULL;
        emp->numScores = 0;
    }
    return emp;
}

void freeEmployee(struct Employee *emp) {
    if (emp) {
        free(emp->name);
        free(emp->scores);
        free(emp);
    }
}

int main(void) {
    struct Employee *emp = createEmployee("John Smith", 3);
    if (!emp) return 1;

    emp->scores[0] = 85; emp->scores[1] = 92; emp->scores[2] = 78;
    printf("Employee: %s\nScores: %d, %d, %d\n", emp->name, emp->scores[0], emp->scores[1], emp->scores[2]);

    freeEmployee(emp);
    return 0;
}
Output
Employee: John Smith
Scores: 85, 92, 78

Common Memory Errors with Structs

  • Memory leaks: Forgetting to free dynamically allocated members
  • Double free: Freeing the same memory twice
  • Use after free: Accessing members after freeing
  • Dangling pointers: Keeping references to freed memory
  • Shallow copies: Copying struct pointers instead of contents
  • Uninitialized pointers: Not setting pointers to NULL
  • Buffer overruns: Writing past struct member boundaries

Advanced Struct Techniques

Advanced struct techniques include:

1. Memory pools for bulk allocations

2. Compiler directives to control padding

3. Flexible array members for variable-sized structs

4. Using unions to share memory

5. Const correctness for safe pointers

6. Memory-mapped files for handling large data

Test your knowledge: C Structs and Memory
Quiz Configuration
8 of 8 questions
Sequential
Previous allowed
Review enabled
Early close allowed
Estimated time: 8 min
C MemoryTopic 62 of 64
←PreviousPrevNextNext→