That solidified my opinion that C and C++ are very different languages despite naive view being that C is just a subset of C++. They're fundamentally different.
That solidified my opinion that C and C++ are very different languages despite naive view being that C is just a subset of C++. They're fundamentally different.
Importantly (see for example https://blog.regehr.org/archives/140) it's not that the standard previously explicitly forbade this sort of optimisation, it's just that it wasn't very clear and compiler writers interpreted it differently.
So in summary, yes, they're different languages, but "modern" C is is less different for this particular thing.
namespace {
void Panic() { while (1); }
} // namespace
extern "C" void kernel() { Panic(); }
The clang++ really does optimize this away:
https://godbolt.org/z/1Wf135918
The same thing happens when I let clang++ compile a C version as C++:
https://godbolt.org/z/MxcGfWhej
However, if I compile it as C with clang, I get an infinite loop:
C++ also broke implicit void pointer conversions, but at least that one had the reason that it was incompatible with function overloading. Not that anyone involved with C++ would tell you this. Instead, they provide bad C code that breaks the strict aliasing rule and claim that breaking implicit void pointer conversions somehow follows from it when in reality that is a non-sequitur:
Using "unused" volatile also works, but it incurs SRAM traffic, which might slow down DMA and cause other effects. So ideally it should be simple empty loop compiled to `b .` instruction (jump to itself).
Another infinite loop usage is for abort() or exit() handler, as a crash place. For this use-case, using "unused" volatile does not cause issues, because device is already crashed, however it still feels wrong.
Why? If you are an experienced C or C++ programmer you know about these quirks. Replacing an infinite loop without side effects with a crash sounds about as "bad" as optimizing it away.