:: Re: [DNG] C vs C++
Top Page
Delete this message
Reply to this message
Author: dvalin
Date:  
To: dng
Subject: Re: [DNG] C vs C++
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.)