vector.c in C
A growable array as a proper little module: create, push, get, destroy.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *items;
size_t len;
size_t cap;
} Vector;
static int vector_init(Vector *v, size_t cap) {
v->items = cap ? malloc(cap * sizeof(int)) : NULL;
v->len = 0;
v->cap = (cap && v->items == NULL) ? 0 : cap;
return !(cap && v->items == NULL);
}
static int vector_push(Vector *v, int value) {
if (v->len == v->cap) {
size_t bigger = v->cap ? v->cap * 2 : 4;
int *grown = realloc(v->items, bigger * sizeof(int));
if (grown == NULL) {
return 0;
}
v->items = grown;
v->cap = bigger;
}
v->items[v->len++] = value;
return 1;
}
static int vector_get(const Vector *v, size_t i, int *out) {
if (i >= v->len) {
return 0;
}
*out = v->items[i];
return 1;
}
static void vector_free(Vector *v) {
free(v->items);
v->items = NULL;
v->len = 0;
v->cap = 0;
}
int main(void) {
Vector v;
if (!vector_init(&v, 2)) {
fprintf(stderr, "out of memory\n");
return 1;
}
for (int i = 1; i <= 10; i++) {
if (!vector_push(&v, i * i)) {
fprintf(stderr, "push failed at %d\n", i);
vector_free(&v);
return 1;
}
}
printf("len %zu cap %zu\n", v.len, v.cap);
int value = 0;
for (size_t i = 0; i < v.len; i += 3) {
if (vector_get(&v, i, &value)) {
printf("[%zu] = %d\n", i, value);
}
}
printf("out of range read: %d\n", vector_get(&v, 99, &value));
vector_free(&v);
return 0;
}
How it works
- The struct is opaque to callers through its functions.
- Every failure path leaves the vector valid and reports it.
mainexercises growth past the initial capacity.
Keywords and builtins used here
NULLconstforifintmainreturnsize_tsizeofstaticstructtypedefvector_freevector_getvector_initvector_pushvoid
The run, in numbers
- Lines
- 73
- Characters to type
- 1301
- Tokens
- 478
- Three-star pace
- 105 tpm
At the three-star pace of 105 tokens a minute, this run takes about 273 seconds.
Step 2 of 2 in Encore, step 25 of 25 in Pointers & memory.