Common libraries and data structures for C

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • JetBrains - Developer Ecosystem Survey 2022
  • Scout APM - Less time debugging, more time building
  • SonarLint - Deliver Cleaner and Safer Code - Right in Your IDE of Choice!
  • sc

    Common libraries and data structures for C.

    If the way it is used requires the user to break the abstraction/encapsulation and manually buffer some fields in order not to break the data structure and leak memory, I would call that a bug.

    There is one use of sc_array_clear() in the test code [1] which really makes it look as if it is being used in a way that I think (again, I haven't single-stepped this code, only read it) leaks memory.

    I agree on the pain of everything being macros, it's more pain than it's worth I think and will likely lead to code duplication (and more pain in debugging, probably).

    I would even go so far as to think that this kind of single-file design, where each file is independent of the others, makes it harder and more annoying to implement more complicated data structures.

    [1]: https://github.com/tezc/sc/blob/master/array/array_test.c#L3...

  • rizin

    UNIX-like reverse engineering framework and command-line toolset.

    Interesting project. We have a similar set of various cross-platform helpers for various C structures and tasks during all these years within Rizin - RzUtil[1]. They are more tightly coupled with each other though and is LGPLv3-licensed.

    [1] https://github.com/rizinorg/rizin/tree/dev/librz/util

    [2] https://github.com/rizinorg/rizin/tree/dev/librz/include/rz_...

  • JetBrains

    Developer Ecosystem Survey 2022. Take part in the Developer Ecosystem Survey 2022 by JetBrains and get a chance to win a Macbook, a Nvidia graphics card, or other prizes. We’ll create an infographic full of stats, and you’ll get personalized results so you can compare yourself with other developers.

  • faun

    A high-level C audio library

    Good stuff. I may make use of the .ini parser as my current one doesn't handle sections.

    There are a growing number of stand alone support modules in my projects that I need to publish as a collection some day. Here's a couple links to some of them:

    - https://github.com/WickedSmoke/faun/tree/master/support

  • u4

    xu4 "Ultima IV Recreated"

    - https://github.com/xu4-engine/u4/tree/master/src/support

    These include more exotic stuff like a grid based field-of-view calculation and a version of the sfxr synthesizer.

  • ccan

    The C Code Archive Network

  • libderp

    C collections. Easy to build, boring algorithms. Dumb is good.

  • pottery

    Pottery - A container and algorithm template library in C (by ludocode)

    I think it's common for C programmers to roll their own. I did the same [0].

    I went pretty deep into composable C templates to build mine so it's more powerful than most. The containers can handle non-bitwise-movable types with full C++-style lifecycle functions and such, and the sort algorithms can handle dynamic and non-contiguous arrays (they are powerful enough to implement qsort() [1], which is more than I can say for any other C sort templates I've seen.) My reasoning for the complexity at the time was that any powerful container library is going to be reasonably complex in implementation (as anyone who's looked at STL source code knows), so it just needs to be encapsulated behind a good interface.

    I'm not so sure that's true anymore. These sorts of simpler libraries like the one linked here definitely seem to be more popular among C programmers. I think if people are using C, it's not just the C++ language complexity they want to get away from, but also the implementation complexity of libraries and such. There's a balance to be had for sure, and I think the balance varies from person to person, which is why no library has emerged as the de facto standard for containers in C.

    [0]: https://github.com/ludocode/pottery

  • Scout APM

    Less time debugging, more time building. Scout APM allows you to find and fix performance issues with no hassle. Now with error monitoring and external services monitoring, Scout is a developer's best friend when it comes to application development.

  • chibicc

    A small C compiler

    It looks like typeof() is being added it C23, so his complaint about it sort of makes sense.

    I say "sort of" because if he's truly concerned about the effort involved in creating independent implementations, then obviously he should be evaluating features by the difficulty involved in implementing them. typedef and typeof are absolutely trivial to implement [0] [1]. typedef just creates type aliases and typeof is essentially the same as sizeof.

    Also, I'm not sure what 1000 functions you're referring to, but most functions being added are already in POSIX and already exist in a huge number of independent libc implementations. There are dozens of POSIX libcs, including at least 5 totally independent implementations for Linux alone that are still fully maintained and under active development.

    [0]: typeof: https://github.com/rui314/chibicc/commit/7d80a5136d1b2926dd0...

    [1]: typedef: https://github.com/rui314/chibicc/commit/a6b82da1ae9eefa44da...

  • libds

    A collection of data structures for C

    I may as well throw my hat into the ring: https://github.com/lelanthran/libds

    I decided that I wanted to be able to simply drop a single .h file and a single .c file into any project without have to build a `libBlah.so` and link it to every project that needed (for example) a hashmap.

    The practical result is that using the hashmap only requires me to copy the header and source files into the calling project.

    It does build as a standalone library too, so you can link it if you want.

    My primary reason for starting this is that I was pretty unsatisfied with all of the string libraries for C. When all I want to do is concatenate multiple strings together, I don't want to have to convert between `char ` and `struct stringtype ` everywhere.

    The string functions are very useful as they all operate on the standard `char *` (nul-terminated) type.

  • stage0

    A set of minimal dependency bootstrap binaries

    Even if they aren't, people absolutely should be able to bootstrap new platforms from scratch. It's important to have confidence in our tools, in our ability to rebuild from scratch, and to be safe against the "trusting trust" attack among other things.

    Lately I've been catching up on the state of the art in bootstrapping. Check out the live-bootstrap project. stage0 starts with a seed "compiler" of a couple hundred bytes that basically turns hex codes into bytes while stripping comments. A series of such text files per architecture work their way up to a full macro assembler, which is then used to write a mostly architecture-independent minimal C compiler, which then builds a larger compiler written in this subset of C. This then bootstraps a Scheme in which a full C compiler (mescc) is written, which then builds TinyCC, which then builds GCC 4, which works its way up to modern GCC for C++... It's a fascinating read:

    https://github.com/oriansj/stage0

    https://github.com/fosslinux/live-bootstrap/blob/master/part...

    Even if no one is "using" this it should still be a primary motivator for keeping C simple.

  • live-bootstrap

    Use of a Linux initramfs to fully automate the bootstrapping process

    Even if they aren't, people absolutely should be able to bootstrap new platforms from scratch. It's important to have confidence in our tools, in our ability to rebuild from scratch, and to be safe against the "trusting trust" attack among other things.

    Lately I've been catching up on the state of the art in bootstrapping. Check out the live-bootstrap project. stage0 starts with a seed "compiler" of a couple hundred bytes that basically turns hex codes into bytes while stripping comments. A series of such text files per architecture work their way up to a full macro assembler, which is then used to write a mostly architecture-independent minimal C compiler, which then builds a larger compiler written in this subset of C. This then bootstraps a Scheme in which a full C compiler (mescc) is written, which then builds TinyCC, which then builds GCC 4, which works its way up to modern GCC for C++... It's a fascinating read:

    https://github.com/oriansj/stage0

    https://github.com/fosslinux/live-bootstrap/blob/master/part...

    Even if no one is "using" this it should still be a primary motivator for keeping C simple.

  • Arduino_EdgeControl

    Arduino Library for Arduino Edge Control

  • Temboo

    Temboo Library for Arduino

  • gcc

    > the terribleness of exceptions is way overhyped

    It's not that exceptions are terrible. I have nothing against them. The thing is that most of the time they are not affordable, especially in embedded. Some compilers don't even support them (some 8-bit IIRC). Most (including mine) embedded C++ programs have exceptions disabled.

    > return a `std::optional`

    The same goes for std. I don't know the overhead of possibly duplicating these classes(1) for every instance of std::optional. Most (including mine) embedded C++ programs don't use std.

    30KB of extra code is nothing for desktop/server applications, but it's not convenient for a MCU with 64KB of flash.

    (1): https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-...

    > just use a factory function instead

    This is practical with an efficient heap allocator (which I might not have). What happens if I want a scoped (on stack) instance of a class?

    See how things are quickly getting more complicated with C++?

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts