C

C Fundamentals

18 lessons

Progress0%
1. Introduction to C
1What is C?
2. Variables and Data Types
1Data Types in C
3. Control Flow
ConditionalsLoops
4. Functions
Defining FunctionsRecursion
5. Arrays and Pointers
Arrays and StringsPointers
6. Memory Management
Dynamic MemoryStructs and Files
7. Preprocessor & Macros
Preprocessor DirectivesMacros & Inline Functions
8. Bitwise Operations
Bitwise OperatorsBit Flags & Masking
9. Enums, Unions & typedef
Enums & typedefUnions & Complex Types
10. Multi-file Programs
Header Files & Compilation UnitsLinkage, Storage Classes & Make
All Tutorials
CMemory Management
Lesson 9 of 18 min
Chapter 6 · Lesson 1

Dynamic Memory

Dynamic Memory Allocation in C

Static arrays have a fixed size known at compile time. Dynamic memory lets you allocate at runtime.

malloc — allocates n bytes, uninitialised:

c
int *arr = (int*) malloc(n * sizeof(int));

calloc — allocates and zero-initialises:

c
int *arr = (int*) calloc(n, sizeof(int));

realloc — resizes an existing allocation:

c
arr = (int*) realloc(arr, new_size * sizeof(int));

free — releases allocated memory back to the OS:

c
free(arr);
arr = NULL;  // prevent dangling pointer

NULL check Always check that allocation succeeded:

c
if (arr == NULL) { fprintf(stderr, "out of memory\n"); exit(1); }

Key points:

  • Every malloc/calloc/realloc must be matched by a free.
  • Forgetting to free causes a memory leak.
  • Using memory after free is use-after-free — undefined behaviour.
  • Set pointers to NULL after freeing to avoid dangling-pointer bugs.

Code Examples

malloc, realloc, and freec
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int n = 5;
    int *arr = (int*) malloc(n * sizeof(int));
    if (arr == NULL) { fprintf(stderr, "malloc failed\n"); return 1; }

    for (int i = 0; i < n; i++) arr[i] = (i + 1) * 10;

    // Grow to 8 elements
    int new_n = 8;
    int *tmp = (int*) realloc(arr, new_n * sizeof(int));
    if (tmp == NULL) { free(arr); return 1; }
    arr = tmp;

    for (int i = n; i < new_n; i++) arr[i] = (i + 1) * 10;

    for (int i = 0; i < new_n; i++) printf("%d ", arr[i]);
    printf("\n");

    free(arr);
    arr = NULL;
    return 0;
}

realloc may move the allocation; always assign the result to a temporary pointer to avoid leaking the original on failure.

calloc and zero-initialisationc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    int rows = 3, cols = 4;
    // Allocate a flat 2D array
    int *grid = (int*) calloc(rows * cols, sizeof(int));
    if (!grid) return 1;

    // Set diagonal
    for (int i = 0; i < rows && i < cols; i++) {
        grid[i * cols + i] = i + 1;
    }

    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < cols; c++) {
            printf("%d ", grid[r * cols + c]);
        }
        printf("\n");
    }

    free(grid);
    return 0;
}

calloc zero-initialises the memory. A flat 1D allocation simulates a 2D array using row*cols+col index arithmetic.

Quick Quiz

1. What is the difference between malloc and calloc?

2. What should you do immediately after `free(ptr)`?

Was this lesson helpful?

PreviousNext