Skip to main content

The Dynamic Array

beginner15 min readLesson 72 of 148

A heap buffer, a count, a capacity โ€” and doubling when full.

The three ingredients

typedef struct {
    int *data;      // heap buffer (malloc/realloc)
    int size;       // elements used
    int cap;        // elements allocated
} DArray;

The invariant that keeps it honest: 0 <= size <= cap, and data either points at a valid allocation of cap ints or is NULL.

Growing by doubling

int da_push(DArray *a, int v) {
    if (a->size == a->cap) {
        int newcap = a->cap == 0 ? 4 : a->cap * 2;
        int *tmp = realloc(a->data, newcap * sizeof(int));
        if (tmp == NULL) return 0;        // old buffer still valid
        a->data = tmp;
        a->cap = newcap;
    }
    a->data[a->size++] = v;
    return 1;
}

Doubling makes N pushes cost O(N) copies TOTAL โ€” the "amortized O(1)" push.

Why this structure wins most of the time

  • index access is O(1) โ€” a single addition and multiply
  • memory is contiguous โ€” cache-friendly
  • the only expensive operation is insertion in the MIDDLE (O(n) shifting)

Most beginner code should reach for a dynamic array first; fancier structures must justify themselves.

Now practice

Dynamic Array BuildConstruct and operate a heap-backed dynamic array module.3 challenges ยท ยท ~18 min