Back to all posts
4 min read

Reinventing the wheel in C: learning data structures from scratch

I've been working as a software developer for a relatively short time, but long enough to internalize a piece of advice I kept hearing everywhere: don’t reinvent the wheel. Use what already exists, rely on libraries, focus on delivering.

I still agree with that.

At the same time, in the last months I started a small side project where I’m doing exactly that: implementing fundamental pieces from scratch in C.

This project lives here: CDS Library.

Right now it includes a dynamic array, quicksort, insertion sort, linear search, and binary search. All written from scratch.

The goal is not to build something production-ready, but to understand these building blocks by implementing them directly.

I write about this kind of exploration under the idea of The Augmented Craftsman: using AI to increase output, while still building a solid understanding of what’s underneath.

How I Used to Approach These Things

Most of my daily work is in C# and .NET. When I need a list or a search, I just use what the framework provides.

I was familiar with the concepts behind those tools. I knew how they were supposed to behave, their complexity, and when to use them. But that knowledge was mostly theoretical.

I didn’t have a clear mental picture of what was happening underneath.

Where the Interest Came From

Part of the push came from a course I found on YouTube by Salvatore Sanfilippo (antirez).

Here’s the course: Antirez C Course.

I’ve always appreciated his work and the way he approaches programming. Watching him go through low-level concepts made me want to try them myself instead of just reading about them.

At the same time, I started feeling a general interest in understanding what sits below the abstractions I use every day.

So I opened a C project and started building.

Working on CDS

I began with a dynamic array. Managing capacity, deciding when to grow, handling reallocations made the behavior very concrete.

Then I moved to algorithms: quicksort and insertion sort. Writing them step by step forced me to focus on details, especially edge cases and performance behavior.

The same happened with linear search and binary search. Binary search, in particular, required precision. Small mistakes in boundaries or conditions break the logic immediately.

The code is simple, but writing it requires attention that I don’t usually need when relying on built-in implementations.

Low-Level Programming and How I’m Using AI

While working on this, I started enjoying programming in a different way.

I still use AI tools every day, but I changed how I use them in this context.

I use AI as a support tool: it helps me debug, suggests improvements, and points out approaches I might miss.

I avoid letting it write the core logic for me. I want to go through the process myself, even when it’s slower.

This approach is slower, but more engaging. I spend more time thinking through problems and less time jumping straight to a generated solution.

Where I Am Now

I’m still at the beginning of this exploration.

The implementations are basic and there’s a lot I don’t know yet. Debugging takes time, and many issues come from small mistakes.

At the same time, I’ve started to build a clearer intuition for some of these concepts. When I use similar structures or algorithms in higher-level languages, I have a better sense of what might be happening behind the scenes.

Why I Keep Working on It

This project doesn’t have a direct impact on my day-to-day work.

I’m using it to understand things more deeply and to explore a part of programming I hadn’t really touched before.

I’ll keep adding small pieces over time and continue in this direction.

I’m still early in this process, but this is the direction I want to explore: going deeper into the fundamentals, while using AI to support the work instead of replacing it.

Written by Christian Borrello

Software Engineer · Craftsman · Lifelong Learner

More posts →