data-structures · intermediate · ~30 min
Modulo-based head/tail indices.
Implement a fixed-capacity int queue:
typedef struct cq cq_t;
cq_t *cq_create(int capacity);
int cq_enqueue(cq_t *q, int v); /* 0 on success, -1 if full */
int cq_dequeue(cq_t *q, int *out); /* 0 on success, -1 if empty */
int cq_size(cq_t *q);
void cq_destroy(cq_t *q);
Ring buffers are everywhere: kernel device drivers, audio playback, network interface cards. The 'one slot wasted' technique distinguishes full from empty.
capacity > 0.
See API.
No realloc. The buffer is allocated once at create.
typedef struct cq cq_t;
cq_t *cq_create(int capacity);
int cq_enqueue(cq_t *q, int v);
int cq_dequeue(cq_t *q, int *out);
int cq_size(cq_t *q);
void cq_destroy(cq_t *q);
Using head == tail to mean both 'empty' and 'full' (ambiguous — use a count, or waste one slot); forgetting to advance with modulo (size_t wraparound only saves you in a few sizes); off-by-one on capacity vs. count.
Dequeue from empty returns -1. Enqueue when full returns -1.
O(1) per op.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.