Macros that evaluate their parameters more than once are dangerous for a
variety of reasons.

On Wed, Jul 29, 2020 at 11:32 AM David Sidrane <david.sidr...@nscdg.com> wrote:
> K&R warns against using macros in loops. Experienced programmers (especially
> embedded) know not to write code like shown in the "reason" for needing this
> change.

True, but at the call site, use of a macro looks just like a function call, so
good macro writing is to make sure it works just like a function call, no
matter where it's used.

Furthermore, over time, the implementation of a macro could change from macro
to function, or from function to macro. Or you might build the application
software on NuttX one day and on a PC OS the next. So if the macro ends up
being used in a loop, it might not be because the programmer is inexperienced,
but because the implementation (or the platform) changed after the code was
written.

Also, you don't know where/how these macros are being used. Perhaps someone is
using a 3rd party library that uses these macros and assumes they are safe.

Because of all these reasons, it is very important, when writing macros, to
make sure they can be used in all possible scenarios without causing problems.

That includes:
* Evaluating parameters once.
* If the macro is multiple statements, as opposed to an expression, wrapping
  those statements in do { ... } while (0).

I think these things are the responsibility of the macro writer, not the macro
caller.

Regarding isalpha() and friends:

On Wed, Jul 29, 2020 at 2:54 AM Xiang Xiao <xiaoxiang781...@gmail.com> wrote:
> 2.Change macro to normal function and lose some performance
> 3.Change macro to inline function and some old compilers may generate
> the bloat code

Given all of the above, and the various concerns voiced here, I think option 2
looks best/safest in the context of embedded systems. While some here might
gawk at the performance penalty of a function call, I agree with Greg that:

> Most released, deeply embedded software  does not do a lot of string
> processing.  So I could imagine that a motor control system that only
> has a couple of uses of ctype functions but would pay a pretty big size
> penalty for using a table.

I think function call overhead isn't quite as horrible as its reputation might
suggest. In fact, if you have macros that evaluate their parameters more than
once, you potentially get a much bigger performance penalty. (I just recently
discovered use of min() and max() macros in code I maintain. Those are
implemented as ((a) < (b)) ? (a) : (b). And the parameters passed to these
macros at the call site were the results of function calls, those functions
were making time-consuming calculations, and they were being executed
redundantly because of the macros evaluating their parameters more than once!
That is a much bigger performance penalty!

On Wed, Jul 29, 2020 at 8:42 AM spudaneco <spudan...@gmail.com> wrote:
> I would consider option 3 to be the worst choice.  That could bloat can be 
> enormous and unacceptable as I have seen in the past.  I saw growth by many 
> kbyte in such cases. Not a good compromise.

I wonder if there exists a good solution for the inline function problem that
will be C89 compliant, avoid the code bloat, and not create a maintenance
nightmare. I don't know what that is yet, but if we find a solution, it will
be helpful for other things besides the isalpha() (and friends) macros.

Nathan

Reply via email to