DEV Community

Cover image for Dynamic Array in C —Complete Guide (Everything You Must Know)
Farhad Rahimi Klie
Farhad Rahimi Klie

Posted on • Edited on

Dynamic Array in C —Complete Guide (Everything You Must Know)

Dynamic arrays are one of the most important low-level data structures in C.
If you do not understand dynamic arrays deeply, you cannot write safe, scalable, or efficient C programs.

This article explains everything about dynamic arrays in C:

  • Memory model
  • Syntax
  • All allocation functions
  • Resizing strategies
  • Internal behavior
  • Common bugs
  • Performance considerations
  • A full dynamic array implementation from scratch

1. What Is a Dynamic Array?

A dynamic array is an array whose size can be decided at runtime and changed later.

Static Array (Fixed Size)

int arr[10];   // size fixed at compile time
Enter fullscreen mode Exit fullscreen mode

Dynamic Array (Resizable)

int *arr = malloc(10 * sizeof(int));
Enter fullscreen mode Exit fullscreen mode

Static arrays:

  • Stored on stack
  • Fixed size
  • Fast but limited

Dynamic arrays:

  • Stored on heap
  • Flexible size
  • Programmer manages memory manually

2. Memory Layout: Stack vs Heap

Understanding memory is mandatory.

+------------------+
|      Stack       |  ← static arrays
+------------------+
|       Heap       |  ← dynamic arrays
+------------------+
Enter fullscreen mode Exit fullscreen mode

Dynamic arrays:

  • Allocated from heap
  • Lifetime controlled by programmer
  • Must be freed explicitly

3. Core Functions for Dynamic Arrays

C provides four essential functions:

Function Purpose
malloc() Allocate memory
calloc() Allocate + zero initialize
realloc() Resize allocated memory
free() Release memory

All are defined in:

#include <stdlib.h>
Enter fullscreen mode Exit fullscreen mode

4. malloc() — Basic Dynamic Allocation

Syntax

void* malloc(size_t size);
Enter fullscreen mode Exit fullscreen mode

Example

int *arr = malloc(5 * sizeof(int));
Enter fullscreen mode Exit fullscreen mode

Important Rules

  • Returns NULL if allocation fails
  • Memory is uninitialized
  • Always check return value

Safe Pattern

int *arr = malloc(5 * sizeof(int));
if (arr == NULL) {
    printf("Memory allocation failed\n");
    exit(1);
}
Enter fullscreen mode Exit fullscreen mode

5. Accessing Dynamic Array Elements

Same syntax as static arrays.

arr[0] = 10;
arr[1] = 20;
printf("%d\n", arr[0]);
Enter fullscreen mode Exit fullscreen mode

Internally:

arr[i] == *(arr + i)
Enter fullscreen mode Exit fullscreen mode

6. calloc() — Zero-Initialized Allocation

Syntax

void* calloc(size_t count, size_t size);
Enter fullscreen mode Exit fullscreen mode

Example

int *arr = calloc(5, sizeof(int));
Enter fullscreen mode Exit fullscreen mode

Difference Between malloc and calloc

Feature malloc calloc
Initialization Garbage Zero
Arguments 1 2
Speed Faster Slightly slower

7. free() — Releasing Memory

Syntax

void free(void *ptr);
Enter fullscreen mode Exit fullscreen mode

Example

free(arr);
arr = NULL;
Enter fullscreen mode Exit fullscreen mode

Why set to NULL?

Prevents:

  • Dangling pointers
  • Double free bugs

8. realloc() — Resizing a Dynamic Array

Syntax

void* realloc(void *ptr, size_t new_size);
Enter fullscreen mode Exit fullscreen mode

Example

arr = realloc(arr, 10 * sizeof(int));
Enter fullscreen mode Exit fullscreen mode

Safe Pattern

int *temp = realloc(arr, 10 * sizeof(int));
if (temp == NULL) {
    free(arr);
    exit(1);
}
arr = temp;
Enter fullscreen mode Exit fullscreen mode

What realloc Does Internally

  • Expands memory if possible
  • Otherwise allocates new block
  • Copies old data
  • Frees old block

9. Growing a Dynamic Array (Manual Resize)

Step-by-Step Example

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

int main() {
    int size = 2;
    int *arr = malloc(size * sizeof(int));

    arr[0] = 1;
    arr[1] = 2;

    size = 4;
    arr = realloc(arr, size * sizeof(int));

    arr[2] = 3;
    arr[3] = 4;

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

    free(arr);
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

10. Shrinking a Dynamic Array

arr = realloc(arr, 3 * sizeof(int));
Enter fullscreen mode Exit fullscreen mode

⚠️ Data beyond new size is lost.


11. Dynamic Array vs Pointer Array (Important)

int *arr;       // dynamic array
int **arr2;     // array of pointers
Enter fullscreen mode Exit fullscreen mode

They are not the same.

Dynamic array:

arr → contiguous memory
Enter fullscreen mode Exit fullscreen mode

Array of pointers:

arr2 → pointers → scattered memory
Enter fullscreen mode Exit fullscreen mode

12. Common Mistakes (Critical Section)

❌ Forgetting sizeof

malloc(10); // WRONG
malloc(10 * sizeof(int)); // CORRECT
Enter fullscreen mode Exit fullscreen mode

❌ Memory Leak

arr = malloc(...);
arr = realloc(arr, ...); // old pointer lost if realloc fails
Enter fullscreen mode Exit fullscreen mode

❌ Use After Free

free(arr);
arr[0] = 10; // undefined behavior
Enter fullscreen mode Exit fullscreen mode

13. Time Complexity

Operation Complexity
Access O(1)
Resize O(n)
Append (amortized) O(1)

14. Real Dynamic Array Implementation (Like vector)

Struct Definition

typedef struct {
    int *data;
    size_t size;
    size_t capacity;
} DynamicArray;
Enter fullscreen mode Exit fullscreen mode

Initialize

DynamicArray arr;
arr.capacity = 2;
arr.size = 0;
arr.data = malloc(arr.capacity * sizeof(int));
Enter fullscreen mode Exit fullscreen mode

Push Back

void push(DynamicArray *arr, int value) {
    if (arr->size == arr->capacity) {
        arr->capacity *= 2;
        arr->data = realloc(arr->data, arr->capacity * sizeof(int));
    }
    arr->data[arr->size++] = value;
}
Enter fullscreen mode Exit fullscreen mode

Free

void freeArray(DynamicArray *arr) {
    free(arr->data);
}
Enter fullscreen mode Exit fullscreen mode

15. Why Dynamic Arrays Matter

Dynamic arrays are the foundation of:

  • vector in C++
  • ArrayList in Java
  • Lists in Python
  • Real-world systems (databases, kernels, compilers)

Mastering them means you understand memory.


16. Summary

You now understand:

  • Heap vs stack
  • malloc / calloc / realloc / free
  • Internal behavior
  • Resizing strategies
  • Memory safety
  • Performance
  • Full implementation

If you understand dynamic arrays, you are no longer a beginner in C.

Top comments (0)