My problems have always been in how memory corruption friendly C happens to be, nothing to do with how to use structured programming practices for resource cleanup.
The structuredness of such inferred jumps usually is both sufficient and convenient, but sometimes being extremely structured leads to boilerplate and inefficiencies. That shows already with early returns from nested scopes, which aren't widely frowned upon, while they are very similar to common usage of goto. I would say I haven't encountered a goto that isn't basically an early return from some nested scope to after some parent or grand-parent scope.
In that sense, a goto can save from having to extract a nested scope as a stand-alone function just to write it as an early return. I would say that many gotos in the wild could be rewritten as early returns after making a standalone function, but maybe sometimes this is too much of a hassle, or, subjectively, puts a toll on readability.
As for structured handling, instead of gotos all over the place, do inverted conditions for early returns similar to what Swift has done with guard statement, embrace functions for resource cleanup, if the cost of a jump brings cold sweat, have them inline and called alongside a return, most compilers will replace calls with jmp opcodes.
What?
> guard
How does it help to have an inverted if statement? Not sure what is the point, can do without.
Goto isn't necessarily for resource cleanup. The common usage is as an early break from the currently executed block, to what comes after the block. Which is often cleanup code, but not necessarily.
shhh. Let's not disturb those that believe in the GC fairy that sprinkles their code with safety magic late at night while they soundly sleep. Firmware doesn't exist. I can't hear you. Na na na na na na na
https://www.withsecure.com/us-en/solutions/innovative-securi...
A good indication of embedded is having to manage shared global state.
This is very unlike a browser where you can hide all that behind OS calls.
And costs the same as an ARM with dozens of megabytes of each.
The only sin of C++ is the same that plagues evolutionary languages like Typescript, Kotlin and so forth.
No matter how many tools they provide to write better code than the language they have grown from, their compatibility with them is like hearding cats while trying to have everyone adopt best practices.
Otherwise in regards to Arduino, I would suggest a couple of nice BASIC and Pascal compilers like those sold by Mikroe.
I'm absolutely coding in C again — writing some old-school games using SDL. After working for decades with various retain/release, garbage-collected, magic-memory™ languages, going back to C feels like programming again. I like it.
Somewhere between 95% and 100% of people who think they're "steeped in C and its quirks, have good coding patterns that allow for it" write code that invokes undefined behaviour.
No, not "the language", but "the standard".
Languages like Python or Rust that don't have standards are 100 percent undefined behavior.
If you're really worried about this, then just code against x86_64 clang and not ISO C++ and forget about this non-problem forever.