On 02.10.24 09:12, nick wrote:
> Didier makes some good remarks re C++. I wholly agree.
...
>
> Apart from that, please avoid C++, and if you must use it, make class hierarchies very shallow and avoid overloading, templates, template base classes, virtual base classes, mixins and multiple inheritance. When these features are overused the result is a horrible spaghetti where the logic of your code is smashed into a million bits sprinkled through your source files in such a way that it is impossible to see what lines of code execute and in what order. Oh the frustration!!!
>
C++ was the new rage back in the 1990s, but I fought it off for our
embedded systems development, after attending a couple of multi-day
seminars presented by some of the founding fathers / famous OO book
authors. In the absence of having burnt my own fingers, I keep this now
14 year old quote from
http://lwn.net/Articles/370717/ :
"One of the pains that come with large C++ programs is that simply
finding code can be difficult. It's not always clear which method will
be invoked in a specific situation, ..."
That seems a recipe for an unmaintainable nightmare, apallingly
expensive in a commercial environment.
I'll now retain your exposition of the issue, as it is much more descriptive.
Incidentally, there are other good ways to buy extra work - though with
some fun on the way. Please don't tell the language mavens that I have
just coded a struct in assembler, for use in an ISR. It uses the .struct
directive of gas. And, of course, addressing elements of the struct is
done by 'pointer + offset' addressing, which the AVR ATmegas support
directly:
ldiw Y,diversion ; Point to that struct with Y register.¹
ldd r16,Y+cycles ; diversion.cycles counts half-cycles,
ldd r17,Y+cycles+1 ; in an int. ²
inc r16 ;
brnz 1f ; (inc does not set the Carry flag.)
inc r17 ;
1: andi r17,0b00000111 ; Cut count to 11 bits, so
std Y+cycles,r16 ; that | std has no status |
std Y+cycles+1,r17 ; on zero we | register impact. |
brnz AC_divert ; measure AC period, once each 20.48 seconds
; at 50 Hz.
(So the struct only exists, at runtime, as pointer arithmetic. ;-)
Granted, that merely implements: if ((diversion.cycles++ & 0x0700) == 0) ...
as a codesize optimised alternative to: if ((diversion.cycles++ == 2048) ...
so the extra hours required to code and debug an embedded
appliction in assembler can perhaps only be justified if you're a
dinosaur who enjoys scratching that itch, or ISR execution time is an
issue. (Debugging raw assembler is akin to a cryptic crossword.
Forgetting to push & pop a clobbered register in an ISR is similar to
forgetting to declare a variable volatile. Much fun can be had before it
is found.)
¹ ldiw is a personal mnemonic, synthesised with a macro, to avoid the
labour of hand coding the two RISC instructions to load immediate a
register pair, extracting high and low bytes of the pointer address in
the process.
² The +1 is compile-time arithmetic, the Y+???? is the aforementioned "register indirect + immediate displacement" addressing mode, good for structs, arrays, and stack frames - all healthy pointer work.
Erik
(Who being on a low-carb diet, avoids excess syntactic sugar.)