26 comments

[ 5.5 ms ] story [ 59.0 ms ] thread
Wow. Saving this playlist to share with coworkers!
This is really great!! My C for Engineering professor was abysmal and I never felt like I got a quality education in it. This is something I've been really wanting to circle back to.
a better take on c vs c++ would be that c++ compilers are much more complex than c compilers, and might not be available on a given small platform. what he says about memory allocation is simply wrong.
A lot of electrical engineers don't know much about how C++ (and C for that matter) actually works.

The real reason to use C in embedded programming is that "vendor_forked_gcc_from_10_years_ago" is your only compiler on most platforms, and almost certainly does not support C++ or has some bugs in its C++ compiler implementation.

There are a couple exceptions here, like Infineon/Cypress’s PSoC chips, but it sort of seems like 99% of vendors have moved to Eclipse based IDEs with full support for whatever compilers work in that ecosystem.

There’s only a handful of things that matter when it comes to generating embedded code for a specific microcontroller and most of it comes down to the format required for the final linked executable, which usually boils down to an ld script.

In general any kind of ARM chip is going to work perfectly fine with the latest C++.

Or to rephrase your comment, the real reason to use C is because all the support tooling, header files, peripheral drivers, RTOS, etc. are written in C, and there’s not a huge benefit to moving user code to C++.

That is really important to note: the spread of the Cortex-M0 has been amazing for embedded software. Before, compilers were vendor-managed for their proprietary core, and now they are basically mainline GCC because of the uniform use of the ARM instruction set.

I remember using a vendor fork of GCC 2 (released in 1999) to compile for a specific microcontroller in 2015, but since that vendor now releases Cortex-M0's, the vendor-blessed compiler uses a near-mainline GCC.

Automotive embedded C developer here. Most of the code in this industry is implemented in a subset of ANSI C90. The reason is not header files, libraries or linker scripts. The reason is as the grandparent post points out: compiler availability.

For rare targets, there's just no money in making a compiler work for more than this small subset of C. My favorite example is the compiler for a really strange architecture where everything is 24 bits. Char is short is long is a pointer.

Bigger controllers tend to be ARM-based, so it's getting better.

Also Tricore has a big share, but their compiler support is getting better. There was even a rust compiler being announced recently, though I doubt it's using LLVM backend, so it's likely to be behind in terms of features.

> Char is short is long is a pointer.

I thought char was required by the C standard to be 8 bits. If everything is 24 bits, how do you cover 24 bit address space with 8 bit pointers?

> I thought char was required by the C standard to be 8 bits

It's not. (EDIT: it is required to be at least 8 bits though)

Welcome to C! The guns are free, but you can only point them at your foot.

The C standard specifies so much less than everyone thinks.

It specifies so much less, precisely to allow it to be usable on such weird architectures.
I wouldn't really qualify this as a foot gun, but rather appropriate flexibility. 98% of people never encounter it, and the 2% that do are happy that it is that way, and I don't think alternative approaches like having the compiler hide it are appropriate for C.
I thought char was required by the C standard to be 8 bits

Common misconception.

to be at least 8 bits though

At least 8 bits for the latter-day compilers for which the 'standard' was the guide. I have seen C compilers where char was 6-bit or 7-bits matching the underlying hardware. However, those probably never implemented more than K&R or some pre-standardization perversion of it.

Also...as noted a char can be more than 8 bits, pre- and post-standardization. I've heard tell of (at least) 9-, 16-, 24- and 32-bit chars on more or less weird platforms.

At some point I'm sure the standards bodies will do some variation of depreciating 8-ish-bit char's for 32-bit Unicode as the standard representation for text.

My favorite example is the compiler for a really strange architecture where everything is 24 bits

DSP? That's the one example I can think of where 24-bit architectures are in active use (and many of them are not Von Neumann, but Harvard with separate data/program memory.)

> The reason is as the grandparent post points out: compiler availability.

is there no appetite to self-write a compiler for the architecture being used?

I'm amazed that such vendors stay in business. Are embedded developers forced to put up with crappy outdated SDKs, because some legacy chipset is $0.01 cheaper per unit?
Yes. Money is king, especially for high volume production. I found in my time at an embedded computer manufacturer that software, especially in house stuff, takes a back seat to everything else.
Multiply by 10 million units and you now save $100,000 by using that chipset. In reality, as I understand it, the price difference is often at least $0.10 between the dirt cheap chip and the one with a nice developer experience.
I kinda love the not-C compiler used for the $.03 Padauk microcontrollers. It's fun, but then again I'm an EE at heart and don't need a lot of abstraction on top of the hardware.
The real reason to use C over C++ is that when you can't use heap allocated memory, you can't use 90+% of C++. At that point, you've inflicted upon yourself all the C++ footguns and have thrown away any of the C++ useful bits.

Once that happens, you might as well just use C.

I disagree with you here. Off the top of my head, these are the things I like about embedded C++ (and embedded Rust):

* RAII makes modern C++ a lot cleaner for things like holding locks, disabling interrupts, and other stuff that needs to be unwound at function exit, and doesn't need heap allocation. Until C gets 'defer', the cleanest alternative is gotos.

* Operator overloading is pretty nice for code where you have custom data types (like 2-element vectors), which can be very common with DSP systems.

* References give you a non-nullable pointer type.

* Template-based data structures are much nicer than the C alternative: macros.

* std::array is kind of nice, and doesn't have dynamic memory. Also, while std::string is pretty unsafe, std::string_view is very nice!

* For the few dynamic data structures you may want to use, you can write a quick allocator and hook that into every std data structure you want rather than writing your own data structures. The "null allocator" strategy is an option: just return the same pointer to one fixed chunk of memory, and fail if the data structure grows too big. You can also do the "init allocator" strategy: Only allow dynamic allocation during initialization.

Having just written a truly repulsive preprocessor hack, I’m currently in my “maybe C++’s monster of a semantics is not that bad actually” phase (it is that bad though, so that’ll pass). C’s metaprogramming facilities are severely lacking. And yet—

> Until C gets 'defer', the cleanest alternative is gotos.

In an embedded setting, a given project is probably only ever targeting a single compiler, and given that in non-exotic situations it’s a vendor fork of GCC, you should be fine using GCC-specific features. And __attribute__((cleanup)) (essentially a block-scoped defer with cleanup code exiled to a separate function) has been in GCC since (checks docs) version 3.3, from 2003. It would have to be a truly spectacular vendor GCC fork to be missing that feature. (For reference, the year 2003 also saw the release of Linux kernel 2.6, as in two-six-zero.)

You can’t use 90% of the STL, sure. But there’s nothing in C++ that requires heap allocation (maybe exceptions? But those are turned off in embedded code anyways)
C++ could be simplified by removing older features, and redundant features that are longer recommended.
Amazing professor! Best class I ever had was his embedded systems assembly/cpu course. Great guy and awesome in person. Throw this man some subs!