Okay, I love C so of course I had to take a look. The buzzwords are impressive, with all the testing and CI and so on, really nice, modern and ambitious.<p>I dove into the code, literally looking at the first true part of the implementation in array/sc_array.h.<p>Two observations, from probably less than tree minutes of reading:<p>1. The nomenclature with "sc_array_term()" as the destructor (the opposite of sc_array_init()) was new to me; I'm not saying that's a real problem but it's at least adding friction in a way. I would have expected sc_array_free(), but that seems to be internally used as an alias for the standard function free(). Very confusing, since that name (sc_array_free()) then leaks into the source but it has the feeling of being meant for internal use.<p>2. I wonder if this has a bug:<p><pre><code> /**
* Deletes items from the array without deallocating underlying memory
* @param a array
*/
#define sc_array_clear(a) \
do { \
(a)->cap = 0; \
(a)->size = 0; \
(a)->oom = false; \
} while (0)
</code></pre>
In my experience, when you want to clear a dynamic array but keep the allocated memory, the 'capacity' ('cap', here) field should <i>not</i> be cleared. I think this will leak memory if an array is grown, cleared, and then re-filled since the sc_array_add() function will see a zero capacity, and allocate new storage.<p>Just my inflation-devalued SEK 0.02, and I did <i>not</i> run the code, I just read it very quickly. Corrections welcome.
As I got more into C programming, I started looking for data structure libraries. Found a few [0]. Also evaluated sc, but it had too much pre-processor magic for my taste. It also bundles random "stuff" like a URI parser, a thread abstraction, etc.<p>Eventually I rolled my own [1] more focused library. It's basic and portable.<p>0: <a href="https://begriffs.com/posts/2020-08-31-portable-stable-software.html#compensating-for-the-standard-library" rel="nofollow">https://begriffs.com/posts/2020-08-31-portable-stable-softwa...</a>
1: <a href="https://github.com/begriffs/libderp" rel="nofollow">https://github.com/begriffs/libderp</a>
Good stuff. I may make use of the .ini parser as my current one doesn't handle sections.<p>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:<p>- <a href="https://github.com/WickedSmoke/faun/tree/master/support" rel="nofollow">https://github.com/WickedSmoke/faun/tree/master/support</a><p>- <a href="https://github.com/xu4-engine/u4/tree/master/src/support" rel="nofollow">https://github.com/xu4-engine/u4/tree/master/src/support</a><p>These include more exotic stuff like a grid based field-of-view calculation and a version of the sfxr synthesizer.
For people advocating use of C++ instead of C, keep in mind there are several platforms (mostly embedded) that only support C and not C++. Also there are many projects that make use of C only. If C++ is available, I agree one should use it, however that is not always the choice.
There's the Clib initiative at <a href="https://github.com/clibs" rel="nofollow">https://github.com/clibs</a>. I don't know how much they curate/review their entries.<p>As often said, <i>apt install foo</i> is also a bit of a package manager for C.<p>Maybe we should establish a sort of expert-led central archive of rock-solid, battle-tested C libs/functions/snippets that one can trust ?
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][2]. They are more tightly coupled with each other though and is LGPLv3-licensed.<p>[1] <a href="https://github.com/rizinorg/rizin/tree/dev/librz/util" rel="nofollow">https://github.com/rizinorg/rizin/tree/dev/librz/util</a><p>[2] <a href="https://github.com/rizinorg/rizin/tree/dev/librz/include/rz_util" rel="nofollow">https://github.com/rizinorg/rizin/tree/dev/librz/include/rz_...</a>
I work in C++ daily and there is something about the simple-ness of C that I love. You get out of magical hell that is templates and return to simple flat-functions and macros.
Good stuff. void* in itself is great for generics. C does support a templating system, like C++, with a little (reasonable) preprocessor abuse. It gives great cache contiguous results: <a href="https://www.github.com/glouw/ctl" rel="nofollow">https://www.github.com/glouw/ctl</a>
With apologies to Greenspun:<p>Any sufficiently complicated C program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of C++.
What I find frustrating when I use C instead of C# is that I have to hunt for libraries and include them in the project or write my own implementation, even for most popular things like data structures, search algorithms, sorting algorithms, serialization, http calls. Whereas in C# the framework will provide them for me. If something is not in the standard library, I can use a directive or just reference a method from a package and the IDE will help to install the package and reference it in the project.<p>Go and Rust are similar in that aspect.
I really like the count prefixed strings, and will be adding it to my grow set of C stuff I'm gathering. My ultimate goal is to have something that does reference counted, count prefixed, null terminated strings, like Free Pascal.<p>I think using the cleanup attribute, and a defer macro can make it happen.
Interesting to look through.<p>I quickly scanned for things that stood out for me. As with anything, there are some things I disagree with.<p>To wit: the condition variable code includes a mutex inside of it, to deal with the case where you perform a signal on something before there is a waiter. Does this solve some problems? Sure. But it introduces extra overhead when I know what I'm doing and just want a condition variable.<p>These types of small things - the author thinks this is the "right thing", whereas others won't - are why no C standard C library like this exists. In C, the beauty is that you make every single decision; someone else's decisions won't be the same as yours.
I don’t understand how after all these years there isn’t a common library that everyone uses for this stuff. There seems to be a bunch of different ones, but not a single standout that most people use. Why not? Where is Boost for C?
Is there something like this but free of allocations at runtime? Things like a queue for example with a preset/defined maximum size of entries that won't suddenly grow but rather tell you that it's full. I made an allocation free JSON parser/serializer once but I don't want to reinvent the wheel all the time ... Embedded devices with low RAM are still a thing and allocation free code is often mandatory.
My old kazlib has the basics: hashing, red-black-tree, lists, exception handling.<p><a href="https://www.kylheku.com/~kaz/kazlib.html" rel="nofollow">https://www.kylheku.com/~kaz/kazlib.html</a><p>Used in e2fsck, Ethereal and others.<p>There is even C++ support hidden in there: the dict.h contains a C++ template wrapper (which keeps the container intrusive).
I'm not a C developer, nor have I ever been interested in developing with it.<p>From my perspective, it seems like a massive time drain and non-productive use of my time. Just a few points:<p>- Tooling seems all over the place (build system, package management)<p>- Having to roll your own trivial functions / types (tooling may play into this)<p>- Versioning is confusing (C99, C11, ???)<p>The only advantage I see would be in embedded software because C is supposedly supported on a lot of platforms and is performant. But, I'm not actually sure this is true in practice.<p>Can you write one file of C code and compile it easily for multiple platforms or is there a lot of caveats?