Live data from Hacker News

Common libraries and data structures for C

github.com

121–130 of 148 posts

Re: Common libraries and data structures for C

#121
post #26

Earlier quoted context omitted.

Keeping it simple to write a compiler is not a serious use case these days. People aren't bootstrapping new platforms from scratch. GCC and Clang are anything but simple.

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…

There are multiple standards for C. C23 does not replace C17, or C11, or C99, or even C89. Maybe something should replace C89, but that's another discussion. I'd vote for C99 as a minimum target and prefer C11.

Just as you yourself described, one can absolutely target a platform from scratch with C99, Forth, Lua, a Pascal, a modernish Basic dialect, or some form of Lisp without building the largest, most modern compiler first. Once you have a compiler or even an interpreter for any of those, one can use it to create a compiler for something bigger and more modern. In fact, that's precisely where C was originally targeted - as a portable bootstrap language to various hardware platforms.

On the other hand, one can also target a new platform via LLVM. Both options have their merits and drawbacks.

Re: Common libraries and data structures for C

#122
post #26

Earlier quoted context omitted.

Keeping it simple to write a compiler is not a serious use case these days. People aren't bootstrapping new platforms from scratch. GCC and Clang are anything but simple.

> Keeping it simple to write a compiler is not a serious use case these days. The implication is that if it is simple to write a parser for a language, then the language is simple to read.

Lisp and Scheme seem to discourage this sort of thinking in a great many programmers. After all, Lisps often start as just the eval function for their S-expressions and grow from there.

See also: Brainfuck, Forth, Chinese

Re: Common libraries and data structures for C

#123

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.

> If C++ is available, I agree one should use it, C is very simple, while C++ is a monster with 100 heads, each speaking in another language. If all members of a project use the same subset of C++, then yes, it would be preferable over C. But if anyone or any team in a large project uses whatever he wants, things can get pretty complicated, pretty fast.

In C, whenever any part of the creature needs to do some thinking, it grows its own small head to do just enough thinking to get by, and then goes about its business. The process is simple, but the result is often Cthulhic.

Re: Common libraries and data structures for C

#124
post #77

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. 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()…

>... /* * Deletes items from the array without deallocating underlying memory * @param a array */

This does look like a bug, if not functionally, then by the described intent. The comment states that the intent is to delete items without deallocating; yet zeroing the capacity cuts any future way to deallocate properly, unless it's just an array of simple types (free(baseptr)). If there are any pointer types, then there will remain no safe way to deallocate the elements' contents.

Sure, there could be other ways of keeping inventory of the allocated memory, but this detaches the array from knowing its allocated bounds.

Re: Common libraries and data structures for C

#125
post #73
post #35

Earlier quoted context omitted.

When 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.

Wait 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.

Compiling 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.

Re: Common libraries and data structures for C

#126
post #109

Earlier quoted context omitted.

> 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 - eve…

> 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 u…

I 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

Re: Common libraries and data structures for C

#127

Interesting 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 vari…

Condition variables must always be used with mutexes.

Re: Common libraries and data structures for C

#128
post #110
post #96

Earlier quoted context omitted.

The same subsets are available in C++ as well, with stronger type checking and RAII for closing those handles. Yeah, safety and IoT unfortunately aren't something that go together. Using C++ doesn't require OOP all over the place, nor crazy template metaprogramming. The same reason you give for using macros.

> RAII C++ is used mostly with exceptions disabled on embedded, so failing constructors are a PITA. You have to keep track of valid states with a bool . Now every function entry has: if (!m_bValid) return; I hate it. > Yeah, safety and IoT unfortunately aren't something that go together. Don't forget that IoT is just a minuscule fraction of embedded. Not everything is connected online or requires safety as top priori…

Yeah, checking return codes is a thing you NEVER have to do in C...

The "exceptions are evil, but without exceptions you can't fail a constructor!" is a really irritating canard when it comes to C++. First off all, the terribleness of exceptions is way overhyped, but even if you do want to avoid them, this is not a problem: just use a factory function instead of a constructor and return a `std::optional` (or a default-constructed value and an error code if you want to avoid `std::optional` for some weird reason).

I like pure C a lot and it definitely has a place in areas like embedded. But this kind reflexive disdain for C++ using uninformed arguments is really tiresome. C++ is fine.

Re: Common libraries and data structures for C

#129
post #125
post #73

Earlier quoted context omitted.

Wait 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.

Compiling 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.

well, 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).

Re: Common libraries and data structures for C

#130
post #128
post #110

Earlier quoted context omitted.

> RAII C++ is used mostly with exceptions disabled on embedded, so failing constructors are a PITA. You have to keep track of valid states with a bool . Now every function entry has: if (!m_bValid) return; I hate it. > Yeah, safety and IoT unfortunately aren't something that go together. Don't forget that IoT is just a minuscule fraction of embedded. Not everything is connected online or requires safety as top priori…

Yeah, checking return codes is a thing you NEVER have to do in C... The "exceptions are evil, but without exceptions you can't fail a constructor!" is a really irritating canard when it comes to C++. First off all, the terribleness of exceptions is way overhyped, but even if you do want to avoid them, this is not a problem: just use a factory function instead of a constructor and return a `std::optional` (or a defaul…

> 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++?

Post reply on HN