Module 10 of 13 · C Programming Fundamentals · Beginner

Dynamic Memory

Duration: 55 min

Dynamic memory allocation allows you to allocate memory at runtime. This is essential for creating data structures of unknown size and managing memory efficiently. C provides malloc, calloc, realloc, and free for dynamic memory management.

malloc Function

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

int main() {
    // Allocate memory for 5 integers
    int *ptr = (int*)malloc(5 * sizeof(int));
    
    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    // Use the allocated memory
    for (int i = 0; i < 5; i++) {
        ptr[i] = i * 10;
    }
    
    // Print values
    for (int i = 0; i < 5; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");
    
    // Free the memory
    free(ptr);
    ptr = NULL;  // Good practice
    
    return 0;
}

calloc Function

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

int main() {
    // calloc: allocates and initializes to 0
    int *ptr = (int*)calloc(5, sizeof(int));
    
    if (ptr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    // All elements are initialized to 0
    for (int i = 0; i < 5; i++) {
        printf("%d ", ptr[i]);  // 0 0 0 0 0
    }
    printf("\n");
    
    free(ptr);
    ptr = NULL;
    
    return 0;
}

realloc Function

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

int main() {
    // Allocate initial memory
    int *ptr = (int*)malloc(3 * sizeof(int));
    
    ptr[0] = 10;
    ptr[1] = 20;
    ptr[2] = 30;
    
    // Resize to 5 integers
    ptr = (int*)realloc(ptr, 5 * sizeof(int));
    
    if (ptr == NULL) {
        printf("Reallocation failed\n");
        return 1;
    }
    
    ptr[3] = 40;
    ptr[4] = 50;
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", ptr[i]);
    }
    printf("\n");
    
    free(ptr);
    ptr = NULL;
    
    return 0;
}

Memory Leaks

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

// BAD: Memory leak
void leaky_function() {
    int *ptr = (int*)malloc(100 * sizeof(int));
    // ... use ptr ...
    // Forgot to free!
}

// GOOD: Proper memory management
void good_function() {
    int *ptr = (int*)malloc(100 * sizeof(int));
    // ... use ptr ...
    free(ptr);
    ptr = NULL;
}

int main() {
    good_function();
    return 0;
}

Dynamic Arrays

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

int main() {
    int n;
    printf("Enter array size: ");
    scanf("%d", &n);
    
    // Allocate array of size n
    int *arr = (int*)malloc(n * sizeof(int));
    
    if (arr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    // Input values
    for (int i = 0; i < n; i++) {
        printf("Enter element %d: ", i);
        scanf("%d", &arr[i]);
    }
    
    // Print values
    printf("Array: ");
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    free(arr);
    arr = NULL;
    
    return 0;
}

Dynamic 2D Arrays

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

int main() {
    int rows = 3, cols = 4;
    
    // Allocate array of pointers
    int **matrix = (int**)malloc(rows * sizeof(int*));
    
    // Allocate each row
    for (int i = 0; i < rows; i++) {
        matrix[i] = (int*)malloc(cols * sizeof(int));
    }
    
    // Initialize and print
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    // Free memory
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);
    
    return 0;
}

Dynamic Structures

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

typedef struct {
    int id;
    char name[50];
    float salary;
} Employee;

int main() {
    int n;
    printf("Enter number of employees: ");
    scanf("%d", &n);
    
    // Allocate array of structures
    Employee *employees = (Employee*)malloc(n * sizeof(Employee));
    
    if (employees == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    
    // Input data
    for (int i = 0; i < n; i++) {
        printf("Employee %d ID: ", i + 1);
        scanf("%d", &employees[i].id);
        printf("Name: ");
        scanf("%s", employees[i].name);
        printf("Salary: ");
        scanf("%f", &employees[i].salary);
    }
    
    // Print data
    for (int i = 0; i < n; i++) {
        printf("%d %s %.2f\n", 
               employees[i].id, 
               employees[i].name, 
               employees[i].salary);
    }
    
    free(employees);
    employees = NULL;
    
    return 0;
}

Best Practices

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

int main() {
    // 1. Always check if allocation succeeded
    int *ptr = (int*)malloc(100 * sizeof(int));
    if (ptr == NULL) {
        printf("Allocation failed\n");
        return 1;
    }
    
    // 2. Use sizeof to avoid hardcoding sizes
    // Good: malloc(n * sizeof(int))
    // Bad: malloc(n * 4)
    
    // 3. Free memory when done
    free(ptr);
    
    // 4. Set to NULL after freeing
    ptr = NULL;
    
    // 5. Don't use memory after freeing
    // printf("%d\n", *ptr);  // DANGER!
    
    return 0;
}

Quiz 1: malloc

❓ What does malloc return if allocation fails?

Quiz 2: calloc vs malloc

❓ What is the main difference between calloc and malloc?

Quiz 3: Memory Leak

❓ What is a memory leak?

Quiz 4: realloc

❓ What does realloc do?

Quiz 5: sizeof in malloc

❓ Why use sizeof in malloc? int *ptr = (int*)malloc(n * sizeof(int))

← Previous Continue interactively → Next →

Related Courses