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
Dynamic Array (Resizable)
int *arr = malloc(10 * sizeof(int));
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
+------------------+
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>
4. malloc() — Basic Dynamic Allocation
Syntax
void* malloc(size_t size);
Example
int *arr = malloc(5 * sizeof(int));
Important Rules
- Returns
NULLif 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);
}
5. Accessing Dynamic Array Elements
Same syntax as static arrays.
arr[0] = 10;
arr[1] = 20;
printf("%d\n", arr[0]);
Internally:
arr[i] == *(arr + i)
6. calloc() — Zero-Initialized Allocation
Syntax
void* calloc(size_t count, size_t size);
Example
int *arr = calloc(5, sizeof(int));
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);
Example
free(arr);
arr = NULL;
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);
Example
arr = realloc(arr, 10 * sizeof(int));
Safe Pattern
int *temp = realloc(arr, 10 * sizeof(int));
if (temp == NULL) {
free(arr);
exit(1);
}
arr = temp;
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;
}
10. Shrinking a Dynamic Array
arr = realloc(arr, 3 * sizeof(int));
⚠️ Data beyond new size is lost.
11. Dynamic Array vs Pointer Array (Important)
int *arr; // dynamic array
int **arr2; // array of pointers
They are not the same.
Dynamic array:
arr → contiguous memory
Array of pointers:
arr2 → pointers → scattered memory
12. Common Mistakes (Critical Section)
❌ Forgetting sizeof
malloc(10); // WRONG
malloc(10 * sizeof(int)); // CORRECT
❌ Memory Leak
arr = malloc(...);
arr = realloc(arr, ...); // old pointer lost if realloc fails
❌ Use After Free
free(arr);
arr[0] = 10; // undefined behavior
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;
Initialize
DynamicArray arr;
arr.capacity = 2;
arr.size = 0;
arr.data = malloc(arr.capacity * sizeof(int));
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;
}
Free
void freeArray(DynamicArray *arr) {
free(arr->data);
}
15. Why Dynamic Arrays Matter
Dynamic arrays are the foundation of:
-
vectorin C++ -
ArrayListin 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)