pointers-memory · intermediate · ~30 min

Grow a dynamic buffer with realloc

Doubling growth strategy and the realloc idiom (use a temporary so OOM doesn't leak the original).

Challenge

Implement a growable byte buffer:

typedef struct { char *data; size_t len, cap; } buf_t;
void buf_init(buf_t *b);
int  buf_append(buf_t *b, const char *bytes, size_t n);  /* returns 0 on success, -1 on OOM */
void buf_free(buf_t *b);

On growth, double capacity (start at 8).

Why this matters

A growable buffer is the kernel of every dynamic string / vector / IO read loop in C. The doubling-growth strategy is what makes append O(1) amortised.

Input format

bytes pointer, n bytes to append.

Output format

0 / -1.

Constraints

Use realloc, not malloc+memcpy+free.

Starter code

#include <stddef.h>
#ifndef BUF_T_DEFINED
#define BUF_T_DEFINED
typedef struct { char *data; size_t len, cap; } buf_t;
#endif
void buf_init(buf_t *b);
int  buf_append(buf_t *b, const char *bytes, size_t n);
void buf_free(buf_t *b);

Common mistakes

p = realloc(p, n) — if realloc returns NULL, you lose the old pointer and leak. Growth by +n (gives O(n^2) total appends). Forgetting to update both len and cap.

Edge cases to handle

First append from cap=0 — need an initial size (typically 8). Append of 0 bytes — no-op. Append larger than current capacity — may need multiple doublings.

Complexity

O(1) amortised per byte. Total O(n) for n bytes across O(log n) reallocs.

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.