pointers-memory · intermediate · ~30 min
Doubling growth strategy and the realloc idiom (use a temporary so OOM doesn't leak the original).
Build a growable byte buffer that appends data and enlarges its backing store on demand using realloc with a doubling growth strategy.
The buffer type and API:
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); /* 0 on success, -1 on OOM */
void buf_free(buf_t *b);
Implement the four functions (no main — the grader calls them):
buf_init zeroes the struct (NULL data, len 0, cap 0).buf_append appends n bytes from bytes, growing capacity (double it, starting at 8) when needed.buf_free releases the backing store and resets the struct to the init state.buf_append receives bytes (source) and n (count, may be 0).
buf_append returns 0 on success or -1 on allocation failure. The other functions return nothing.
buf_t b; buf_init(&b);
buf_append(&b, "hi", 2); -> b.len == 2, b.cap >= 2
buf_append(&b, ", world!", 8); -> b.len == 10, data == "hi, world!"
buf_free(&b); -> data == NULL, len == 0, cap == 0
n == 0): no-op, returns 0.cap == 0: start capacity at 8 (or larger if needed).realloc into a temporary so an OOM doesn't leak the original buffer.n.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.
buf_append: source bytes and byte count n (may be 0).
buf_append returns 0 on success, -1 on OOM; other functions return nothing.
Use realloc (into a temporary), not malloc+memcpy+free. Double the capacity, starting at 8.
#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);
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.
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.
O(1) amortised per byte. Total O(n) for n bytes across O(log n) reallocs.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.