Hacker News new | ask | show | jobs
by israrkhan 1493 days ago
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.
5 comments

> 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.
If the team doesn't care about code reviews, static analysis and automatic formating tools on PR merges, surely.
Unless we are talking about something like Z80, 6502, PIC, AVR and similar low end CPUs, which hardly full support even C89, all modern CPUs have C++ compilers available.

More often than not, it is a matter of not wanting to use C++ than it not being available.

On most embedded systems you cannot include std. You don't have a decent memory allocator. Bad use of templates will consume all of your flash space (code duplication).

Yes, it can work for simple Arduino sketches, and I won't say that there are not complex embedded projects in C++.

But... why should I want to use C++?

For one, I use a small subset, like it's C with classes. I like function overloading and default argument values, initializing default values for some structs, not having to type typedef struct, the fact that for a time I could declare variables mid-function and using literal bool, true, false, etc.

But full-blown C++ on embedded (MCU)? I think I'll pass.

You cannot also use stdio and most stdlib, so what?

You would want to use C++ for stronger type safety, proper enumerations, templates instead of undebuggable macros, namespaces,....

https://news.ycombinator.com/item?id=31406942

"CppCon 2016: Jason Turner “Rich Code for Tiny Computers: A Simple Commodore 64 Game in C++17”"

https://www.youtube.com/watch?v=zBkNBP00wJE

MCUs also don't support full-blown C, and it isn't a show stopper to keep advocating it, so why should it be for a language with better safety options, even with constraints.

> You cannot also use stdio and most stdlib, so what?

You can still use a subset of stdio and stdlib. Newlib also provides hooks you can use to implement fopen and the like, if you want.

> better safety options

Safety is not always the utmost priority. At least, not that kind of safety. It seems people forget this concept from time to time.

> templates instead of undebuggable macros

This is if you use complex macros, which is not always the case. I've been doing embedded for 20 years and I rarely (very rarely) find problems with macros.

But you know what's undebuggable on embedded? Complex inheritance, which sooner or later you'll hit with OOP.

For a system in which you don't have a screen, or logs, or any kind of output, that is usually not in your table, and you have to study failures by telling someone to look at an LED, or by guessing what could have gone wrong, you have to keep your system simple.

Add templates to the mix and good luck opening the project six months later, when a customer calls with a problem.

Edit: But again, used with caution, C++ can be used in embedded, at least the way I use it, as explained before.

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

> Using C++ doesn't require OOP all over the place, nor crazy template metaprogramming.

So we agree. But I think you should be considering the possibility that there might be something going on between you and C, and that it could be possible that not every C developer out there is out of their mind (considering the quantity of past, present and future C projects).

Make peace with C, because the world runs on C and we'll be long gone by the time C will be replaced by something else :)

> More often than not, it is a matter of not wanting to use C++ than it not being available.

That's perfectly valid. I reach for C when I need to write fairly small programs. When C does not fill my needs anymore, I don't reach for C++. There are better high-level languages.

C++ is not a replacement for C. When one of the worlds foremost experts on C++ complains that the language is too complex to understand[1], passing on C++ is a reasonable position.

[1] https://steven.brokaw.org/posts/scott-meyers-cant-remember-c...

Same critic can be applied to any language of the same age as C++.

Try to do a pub quizz about a begginiers friendly language like Ruby or Python, that spans over all their versions.

I agree with you. I'm a bit tired of C++ being imposed on those that rather just use C or as if C users can't turn to any other options besides C++. To include that C interop has become a thing for many newer programming languages now.

By the way, the D language (which has been with us for a while) has long positioned itself as a viable alternative to C++.

Why do you mention AVR? AVR-GCC has C++ support, that's what made the original Arduino (before they switched to ARM) approachable to beginners.
> AVR-GCC has C++ support

It's a very restricted subset of C++ that has almost no advantages over plain C, and some number of disadvantages.

- templates instead of macros

- constexpr instead of macros

- if constexpr instead of macros

- stronger type checking

- type inference

- strong type enumerations

- namespacing instead of pre-historic naming prefixes

- classes as means to enforce type invariants

I see some advantages.

List of typical 8 bit CPUs, and I was thinking only about commercial compilers.
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.

Yes, 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...

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).
> Wait you ssh into a BeagleBoneBlack and compile C on the device?

Exactly how am I supposed to access the hardware that only exists on the Beaglebone Black itself, otherwise?

You can cross-compile all day, but, in the end, I need to code to be running over there to toggle those GPIOs. I need the debugging to be over there. I need VSCode to be running over there.

Not all programming is web programming.

I mean, theoretically it's possible to set up a cross-compilation environment (which would require mirroring basically the entire /usr of the BBB) and copy over compiled files for running / debugging. But it's only worth it if compiling takes a long time (or I suppose if you were to use templaty C++ or rust or something, you may not have enough memory on the BBB to actually compile things... but maybe don't do that?).
rust actually does okay on the BBB unless you activate heavy macros at which point the memory blows up, and it grinds to a halt.

rust-analyzer, for example, could be built (slowly) on the BBB until recently. The last refactoring of it ... ooof ... did something to macros and now the memory footprint is gargantuan.

Somehow I enjoy writing C much more than C++
Embedded devices really opened my eyes to this world. What a fool I was using malloc on my first Arduino project.
Arduino is entirely C++ though
> Arduino is entirely C++ though

No, it's C++ without exceptions (so constructors are useless).

On Arduino you will almost certainly program in a C-with-classes manner; lack of exceptions make almost everything that C++ brings to the table useless[1].

> lack of exceptions make almost everything that C++ brings to the table useless[1].

sorry what ? constexpr (https://github.com/arduino-libraries/Arduino_EdgeControl/blo...), templates (https://github.com/arduino-libraries/Temboo/blob/dcce3007eb5...), etc. are all widely used in the Arduino community. I've recently done some work involving C++20 coroutines on an RP2040. etc etc...

And even without exceptions, RAII can still help ensuring a large amount of invariants automatically.

It is remarkable how many large and modern C++ code bases somehow make thorough use of the language, including constructors, without exceptions. Unless the asserted need for exceptions is a gross mischaracterization.