30 ms·
Common libraries and data structures for C
- darknavi 4y agoI 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.
- LeSaucy 4y agoHot take: people make a bigger deal of how complex templates are. Modern compilers find and describe errors much better than in the days of trying to use boost in vc6.
- orlp 4y agoTemplates suck because they're the wrong abstraction. Or rather, they pretend to be an abstraction when in reality they're leaky as hell. Rust's traits are generics done right. I haven't looked at Concepts too much, I hope that they'll be better than templates.
- pjmlp 4y agoThey are, the best ISO C++ alternative is ISO C++ vnext.
- DeathArrow 4y agoYou can take a look at C# generics. They are quite simple.
- webmobdev 4y agoD is more appealing and powerful, and if you are familiar with C/C++ there's not much of a learning curve - https://dlang.org/overview.html https://dlang.org/overview.html
- pjmlp 4y agoNothing prevents you to code like that in C++, although I would rather suggest templates instead of macro hell.
- huhtenberg 4y agoThat's the thing with C and C++. C is light and simple, but don't use it much, because it can get too verbose. C++ allows for succinct code, but it's neither light or simple. Nor does it have any concern for the elegance of its design. Hence the common practice of using a small subset C++ and pretending it's just C with Extras.
- einpoklum 4y ago> Nor does it have any concern for the elegance of its design. It has a lot of inelegant facilities, which, when used under the hood, allow you to express your elegant abstractions. > Hence the common practice of using a small subset C++ and pretending it's just C with Extras. That's mostly failure to use C++. Since C++11, and especially with later updates to the standard, idiomatic C++ is very different from C - even if you're not using a lot of the standard library. I'll link to a talk already linked-to in another comment in this discussion: Rich code for tiny computers / Jason Turner, CppCon 2016 https://www.youtube.com/watch?v=zBkNBP00wJE https://www.youtube.com/watch?v=zBkNBP00wJE
- _gabe_ 4y ago> That's mostly failure to use C++. Isn't this the no true Scotsman fallacy? It looks like you're agreeing with the parent poster that a lot of people use a small subset of C++ to pretend that it's C with extras. If this is true, it's not a failure of all these people because they don't _really_ understand C++. It's a failure of the language designers because they have made something that nobody can agree on how to use.
- einpoklum 4y agoI should have used a different word. I meant "failure to do X" as in "not doing X", not as in "lack of success in the attempt to do X" See the two meanings here: https://dictionary.cambridge.org/dictionary/english/failure https://dictionary.cambridge.org/dictionary/english/failure
- huhtenberg 4y ago
- bowsamic 4y agoI 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?
- teddyh 4y agoThe closest I’ve seen is GLib: https://wiki.gnome.org/Projects/GLib https://wiki.gnome.org/Projects/GLib
- xvilka 4y agoInteresting 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. [1] https://github.com/rizinorg/rizin/tree/dev/librz/util https://github.com/rizinorg/rizin/tree/dev/librz/util [2] https://github.com/rizinorg/rizin/tree/dev/librz/include/rz_util https://github.com/rizinorg/rizin/tree/dev/librz/include/rz_...
- sydthrowaway 4y agoWhy not use GObject?
- sbf501 4y agoI think writing your own portable C functions is something every programmer wants to own at some point in their young career. Then you grow up and realize there are entire organizations that have spend tens of thousands of man-hours providing the same code, but done correctly and with intent (and consistent philosophy). GObject is that philosophy, but lots of people never hear about it until someone says "Why not use GObject?" :)
- slabity 4y agoThis is completely anecdotal, but when I was looking for something like this ~10 years ago (and was just beginning to learn about the wider Linux ecosystem outside of libc), I stumbled upon GObject and completely ignored it because of its association with GNOME. My initial thoughts was that GObject was only really useful if you were building things for the GNOME ecosystem and wrote it off completely. I also did the same with GLib. I know now that the association only really goes as far as who maintains it, but if it wasn't for how it was branded, I probably would have been using it in a lot more of my projects. Sounds kind of stupid, but never underestimate how branding can affect how your project gets used. Especially by people who are unfamiliar with it.
- zambal 4y agoYour comment could have been mine. Many years ago, I found GObject interesting, but was afraid using it would lead to friction when used outside GNOME's ecosystem.
- sbf501 4y agoI was referring to myself too in my original post, but I don't think it was clear. I resisted GObject/GLib for the exact same reasons you listed. Plus as a younger programmer I was super fussy about style conventions and didn't like introducing other styles with my "pure" style. (I know, I know.) It wasn't until I started using GStreamer that I saw the light.
- WickedSmoke 4y agoGood 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 https://github.com/WickedSmoke/faun/tree/master/support - https://github.com/xu4-engine/u4/tree/master/src/support 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.
- glouwbug 4y agoGood 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: https://www.github.com/glouw/ctl https://www.github.com/glouw/ctl
- metadat 4y agoProbably best to disclose you're pitching your own baby to us. What do you feel this content adds in context of the article? I can't tell.
- gnufied 4y agoYou mean why would anyone link another useful C library in a thread about C libraries - you can't tell?
- metadat 4y agoWithout any explanation it's probably not useful to most of us.
- synergy20 4y agothey're kind in the same category to me, good to know both and compare them.
- cestith 4y agoI thought "glouw" in the username here and in the username in the link was pretty obvious myself.
- glouwbug 4y agoI mean, it’s not like I’m plugging retail source ;)
- quickthrower2 4y ago
- 4dnightmare 4y agoLooks good
- hypeatei 4y agoI'm not a C developer, nor have I ever been interested in developing with it. From my perspective, it seems like a massive time drain and non-productive use of my time. Just a few points: - Tooling seems all over the place (build system, package management) - Having to roll your own trivial functions / types (tooling may play into this) - Versioning is confusing (C99, C11, ???) 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. Can you write one file of C code and compile it easily for multiple platforms or is there a lot of caveats?
- bigDinosaur 4y agoC is of course a terrible waste of time for most tasks today. It is performant and widely supported though. The main thing with it is that you simply cannot avoid it in certain areas, it's C or bust. Now, let's talk about how much time C++ wastes ;)
- TingPing 4y agoBeen doing it for 15 years. C is a very stable target and easy to use. Portability doesn't come out of the box but is doable with a single abstraction library of your preference.
- deleted 4y ago[deleted]
- sylware 4y agoC is supposely a language which it is reasonable to write a compiler for and in order to get a reasonable hardware ISA abstraction. Don't worry, the ISO working groups are making sure that it won't last and soon writting a C compiler will become a nightmare like what they did for c++ (C23 is seriously scary). Instead they should fix it: remove _Generic, typeof, etc which have nothing to do there, and make sure writting a C compiler does keep requiring only a reasonable amount of developement efforts (not an army of devs for 20 years like c++). Actually, removing and hardening stuff would be more appropriate, namely not really adding stuff: remove typedef? harden and improve the type casting rules, let's be bold and eat the bullet, remove the implicit cast except to/from void* pointers and add static/dynamic casts (please not with the c++ syntax)? Make function pointers the same than the other pointers, finally (POSIX/GNU requires it though). Etc.
- patrck 4y agoI guess CCAN died? https://ccodearchive.net/ https://ccodearchive.net/
- hackernudes 4y agoRusty must be too busy working at Blockstream!
- somerando7 4y agoThe lengths people will go to not use C++ is staggering.
- c3534l 4y agoYes, writing libraries and tools. The horror.
- DeathArrow 4y agoI see nothing wrong in having a preference if both C and C++ can be used for the same project and if the development speed is roughly the same.
- lelanthran 4y ago> The lengths people will go to not use C++ is staggering. Every C thread on every forum always has some C++ proponent jumping in to bemoan that people prefer one of the simplest languages over, literally, the most complex (from a programmer PoV) language in existence. Is it really such a stretch to believe that people prefer readability and maintainability over expressive power? The "lengths" in this case is small - a once of cost of a few days to implement vector and string functions gets you most of what most developers need and want.
- ImprobableTruth 4y agoYeah, having to define all vector functions as macros is definitely the epitome of readability and maintainability.
- wruza 4y agoIn this specific case I think we have to agree with your point. When code have to go all-.h, it’s already reasonable to go [a subset of] C++.
- somerando7 4y agoEvery single time there are some people who love C (in my experience for the reason they haven't worked professionally in C++) that claim that they're actually WAY more productive and readable when working in C. C++ is basically almost a perfect super-set of C. Use the parts of C++ that are useful to you, don't use the parts that aren't. Clearly std::vector, std::string, std::unordered_map would be ultra useful to anyone. Especially because they are easier to use, more optimized, not as prone to errors as their C equivalents. I blame Jonathan Blow and Muratori for this. They somehow got the entire gamedev community to worship the idea of writing things in C. People grow out of it really fast though, as soon as they actually learn C++.
- RcouF1uZ4gsC 4y agoWith apologies to Greenspun: Any sufficiently complicated C program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of C++.
- acuozzo 4y agoThe Linux kernel doesn't.
- israrkhan 4y agoFor 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.
- cozzyd 4y agoWhen working on some platforms (e.g. BeagleBoneBlack), the compilation time of C++ is a huge turnoff. Sure, you can cross-compile, but that feels like even more friction.
- NavinF 4y agoWait you ssh into a BeagleBoneBlack and compile C on the device? I’ve seen some janky envs in my life but this is pretty high up. Do you never enable LTO when linking deps? These devices are literally 1000x slower than a typical 8 core desktop.
- cozzyd 4y agoYes, and edit/debug code in the device too. Setting up an identical cross compilation environment with all the same shared libraries (it's a full Linux system after all) and such is non-trivial and C compiles fast enough it's fine... (1000 times is a bit of an exaggeration anyway...) Now maybe if I were an emacs user this setup wouldn't work...
- megous 4y agoCompiling a single C file program, linking glib, libarchive and some other stuff (repeated runs, to allow for caching inputs): Orange Pi 3: real 0m0.916s user 0m0.839s sys 0m0.074s 5950X real 0m0.080s user 0m0.064s sys 0m0.016s Slower, but not nearly 1000x in practice. Cortex-A8 is a bit slower, still, but not by much.
- cozzyd 4y agowell, one project I work on compiles ~100 times faster on my desktop (Ryzen 5 3600) than the BBB if building from scratch, and that's not accounting for multiple cores, so 1000x might be reasonable for a project with sufficient compile-time parallelization. But it's still fast enough (< 10 seconds ) on the BBB that setting up a cross-compilation environment isn't worth it (and obviously incremental compiles are faster).
- begriffs 4y agoAs 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. Eventually I rolled my own [1] more focused library. It's basic and portable. 0: https://begriffs.com/posts/2020-08-31-portable-stable-software.html#compensating-for-the-standard-library https://begriffs.com/posts/2020-08-31-portable-stable-softwa... 1: https://github.com/begriffs/libderp https://github.com/begriffs/libderp
- ludocode 4y agoI 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 https://github.com/ludocode/pottery [1]: https://github.com/ludocode/pottery/tree/develop/util/pottery/qsort https://github.com/ludocode/pottery/tree/develop/util/potter...
- rwbt 4y agoThanks for sharing! This looks like a very well designed container library.
- jandrese 4y agoDid you look at glib? It has quite a lot of features and is pretty easy to use.
- DeathArrow 4y agoWhat 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. Go and Rust are similar in that aspect.
- cowtools 4y ago>Go and Rust are similar in that aspect. I think this poses a subtle security risk about namespacing. Who authorizes these packages? Who audits these repositories? When you use a C/C++ library, there is obvious accountability. You know who maintains the repository (usually your distribution) or you explicitly copy someone elses code as a subrepository.
- xigoi 4y agoIf you trust the compiler, why wouldn't you trust the standard library? They're usually made by the same people.
- lelanthran 4y ago> If you trust the compiler, why wouldn't you trust the standard library? They're usually made by the same people. That sounds like a different way of saying "they're sometimes made by different people", which is why you won't trust it.
- xigoi 4y agoBy different people that have been approved by the compiler developers.
- cowtools 4y agoI am talking about non-standard libraries
- alcover 4y agoThere's the Clib initiative at https://github.com/clibs https://github.com/clibs. I don't know how much they curate/review their entries. As often said, apt install foo is also a bit of a package manager for C. Maybe we should establish a sort of expert-led central archive of rock-solid, battle-tested C libs/functions/snippets that one can trust ?
- HerrMonnezza 4y agoMaybe we should establish a sort of expert-led central archive of rock-solid, battle-tested C libs/functions/snippets that one can trust ? GNUlib [1], albeit marketed as a "portability library", in fact shares a lot of that goal and includes data structure implementation, OS interfaces, etc. A couple of excerpts from the docs: * "Gnulib is intended to be the canonical source for most of the important “portability” and/or common files for GNU projects. These are files intended to be shared at the source level" [3] * "We develop and maintain a testsuite for Gnulib. The goal is to have a 100% firm interface so that maintainers can feel free to update to the code in git at any time and know that their application will not break." [3] [1]: https://www.gnu.org/software/gnulib/manual/html_node/index.html https://www.gnu.org/software/gnulib/manual/html_node/index.h... [2]: https://www.gnu.org/software/gnulib/manual/html_node/Gnulib-Basics.html https://www.gnu.org/software/gnulib/manual/html_node/Gnulib-... [3]: https://www.gnu.org/software/gnulib/manual/html_node/High-Quality.html https://www.gnu.org/software/gnulib/manual/html_node/High-Qu...
- alcover 4y agoWell.. that'll do it ! I wonder how I never stumbled upon that massive trove.
- lloydatkinson 4y agoSeems to be mostly aimed at desktop OSs from a look at the source. How about one that’s platform independent, for embedded systems for example?
- unwind 4y agoOkay, 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. I dove into the code, literally looking at the first true part of the implementation in array/sc_array.h. Two observations, from probably less than tree minutes of reading: 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. 2. I wonder if this has a bug: /** * 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) In my experience, when you want to clear a dynamic array but keep the allocated memory, the 'capacity' ('cap', here) field should not 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. Just my inflation-devalued SEK 0.02, and I did not run the code, I just read it very quickly. Corrections welcome.
- danielEM 4y agoI see just one GH issue and it is none of yours above, why? As for someone claiming so much appreciation for C it seem like your love is a bit toxic ;-) (no offense here).
- antirez 4y agoThe macro does not look (necessarily) as a bug, it simply does a counter intuitive thing of zeroing everything, including the capacity. Maybe the way it is used, the capacity is saved, then the array cleared, then it is set back; or more likely it is used only after the allocation of the object, when everything requires to be zeroed (but if this is the case it should be called "_init" and not "_clear", for clarity). Does not look as the most sounding interface of course. Also this is the kind of thing that should not be done as macro regardless of speed... and only turned into a macro in case of very aggressive profiler-drive optimization.
- mikewarot 4y agoI 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. I think using the cleanup attribute, and a defer macro can make it happen.
- numlock86 4y agoIs 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.
- Upvoter33 4y agoInteresting to look through. I quickly scanned for things that stood out for me. As with anything, there are some things I disagree with. 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. 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.
- cryptonector 4y agoCondition variables must always be used with mutexes.
- bjourne 4y agoI don't understand why so many functions are implemented as macros when C99 has the inline keyword.
- Danielle69 4y ago
- kazinator 4y agoMy old kazlib has the basics: hashing, red-black-tree, lists, exception handling. https://www.kylheku.com/~kaz/kazlib.html https://www.kylheku.com/~kaz/kazlib.html Used in e2fsck, Ethereal and others. There is even C++ support hidden in there: the dict.h contains a C++ template wrapper (which keeps the container intrusive).