0Pricing
C Academy · Lesson

A Reusable Vector Type

Wrap size and capacity.

A Reusable Vector Type is a free C Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

From Loose Code to a Type

Passing around a pointer, a count, and a capacity as three separate variables is error-prone.

Let's bundle them into one struct: a reusable dynamic array, often called a vector. It packages the data and the bookkeeping together.

The Vector Struct

A vector needs three fields: a pointer to the data, how many elements are used (len), and how many fit before resizing (cap).

typedef struct {
    int    *data;
    size_t  len;
    size_t  cap;
} Vec;

Initializing a Vector

An empty vector has a NULL data pointer and zero length and capacity. A small init function makes the intent clear.

void vec_init(Vec *v) {
    v->data = NULL;
    v->len = 0;
    v->cap = 0;
}

The Push Operation

vec_push adds one element to the end. If the vector is full, it doubles the capacity first.

It returns 0 on success and -1 if allocation fails, so callers can react.

int vec_push(Vec *v, int value) {
    if (v->len == v->cap) {
        size_t nc = v->cap ? v->cap * 2 : 4;
        int *tmp = realloc(v->data, nc * sizeof(*v->data));
        if (!tmp) return -1;
        v->data = tmp;
        v->cap = nc;
    }
    v->data[v->len++] = value;
    return 0;
}

Reading Elements Back

Because len tracks the used count, you iterate from 0 to len - 1. The capacity may be larger, but those slots aren't part of your data yet.

for (size_t i = 0; i < v->len; i++)
    printf("%d\n", v->data[i]);

Freeing the Vector

A vector owns its heap buffer, so it needs a matching cleanup function. After freeing, reset the fields so the struct can't be misused.

void vec_free(Vec *v) {
    free(v->data);
    v->data = NULL;
    v->len = v->cap = 0;
}

Putting It Together

This full program builds a vector, pushes five values, prints them, then frees it cleanly.

#include <stdio.h>
#include <stdlib.h>

typedef struct { int *data; size_t len, cap; } Vec;

int vec_push(Vec *v, int value) {
    if (v->len == v->cap) {
        size_t nc = v->cap ? v->cap * 2 : 4;
        int *tmp = realloc(v->data, nc * sizeof(*v->data));
        if (!tmp) return -1;
        v->data = tmp; v->cap = nc;
    }
    v->data[v->len++] = value;
    return 0;
}

int main(void) {
    Vec v = {0};
    for (int i = 0; i < 5; i++) vec_push(&v, i * 10);
    for (size_t i = 0; i < v.len; i++) printf("%d\n", v.data[i]);
    free(v.data);
    return 0;
}

Zero-Initializing with {0}

Writing Vec v = {0}; sets every field to zero, including the data pointer to NULL.

This is a handy shortcut that makes a vector ready for vec_push without calling an explicit init function.

Vec v = {0};      /* data=NULL, len=0, cap=0 */
vec_push(&v, 42);

A Safe get Helper

Indexing past len is a bug. A small accessor can check bounds and signal errors, trading a little speed for safety.

int vec_get(const Vec *v, size_t i, int *out) {
    if (i >= v->len) return -1;   /* out of range */
    *out = v->data[i];
    return 0;
}

Why Track len and cap Separately

cap is how much memory is allocated; len is how much you actually use.

Keeping spare capacity means most pushes don't call realloc. This separation is what makes a vector both fast and flexible.

Generalizing the Type

This vector stores int. To hold other types you can change the element type, or store void * with an element size.

The pattern, init, push, free, stays the same regardless of what you store.

typedef struct {
    double *data;
    size_t  len, cap;
} DVec;   /* same shape, different element type */

Quick Check

Test your understanding of the vector type.

Recap

A vector bundles a data pointer, len, and cap into one struct.

vec_push doubles capacity when full, vec_free releases the buffer and resets fields, and {0} initializes cleanly. This reusable pattern beats juggling loose variables. Next: freeing correctly and avoiding leaks.

Frequently asked questions

Is the “A Reusable Vector Type” lesson free?

Yes — the full text of “A Reusable Vector Type” is free to read here on the web, and the C Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO.

What will I learn in “A Reusable Vector Type”?

Wrap size and capacity. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C Academy?

No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “A Reusable Vector Type” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C Academy lesson?

Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Allocating an Array
  2. Growing with realloc
  3. A Reusable Vector Type
  4. Freeing and Avoiding Leaks
← Back to C Academy