Pages: 1 2 [3]   Go Down
Author Topic: min, max, abs.. are macroses?  (Read 7159 times)
0 Members and 1 Guest are viewing this topic.
Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2346
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

While the code that is provided by the Arduino development environment,
(core code and libraries), does not have any C code that currently uses these macros
At this point, there is no reason not to.
seems to a bit of an overstatement with respect to creating a C++ only solution.

Quote
Why does the solution need to work for C?

So that it can be finally be put to bed rather than having to revisit this again
in the future when something in a C module "breaks".
Maybe it is a 3rd party library, or heaven forbid some
new C code in say the Due C core code wants/needs to use these type of macros.

IMHO, this kind of stuff really should be done by the compiler and LibC people rather than being done
in individual projects.

Of course, another approach, which would carry on in the seemingly odd, IMHO, Arduino/Wiring Language
"Re-Inventing the Wheel Syndrome", would be to create new Class/Macro/Template "functions"
with names like Min(), Max(), Abs(), Constrain(), and Round() that do what the old functions/macros
did.

But even if you do that, you still need to fix the existing min()/max() ... macros.

--- bill
« Last Edit: January 12, 2012, 07:14:20 pm by bperrybap » Logged

Seattle, WA
Offline Offline
God Member
*****
Karma: 8
Posts: 673
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

But even if you do that, you still need to fix the existing min()/max() ... macros.

Simple solution would be to wrap the old-school stuff in the #else of #ifdef __cplusplus.  That way, the modern folks can have a well-behaved compiler-driven solution, and people who for some reason like C *and* Arduino, can have something that works.

Moreover, the focus in Arduino is folks who are new to all this.  These folks will not need C, and they are more likely to be tripped up by accidentally using 'max' somewhere in their code and getting arcane error messages.  I think it's fair to say that anyone using C on Arduino knows what they're doing, and can pull in a C implementation of min/max without any problem.
Logged


SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6378
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I guess the chief danger is that a user's Arduino habits would suddenly cause them to write non-working code in a C environment.  A C++ only solution would cause C++ to behave differently than C (silently.  Invisibly.)

Quote
this kind of stuff really should be done by the compiler and LibC people
Agreed.  It looks as though "abs" has already been handled by the compiler.

Quote
"The ISO C90 functions abs, cos, exp, fabs, fprintf, fputs, labs, log, memcmp, memcpy, memset, printf, putchar, puts, scanf, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function). All of these functions have corresponding versions prefixed with __builtin_."
http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Other-Builtins.html
Logged

Belgium
Online Online
Edison Member
*
Karma: 58
Posts: 1736
Arduino rocks; but with my plugin it can fly rocking the world ;-)
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

maniacbug
Quote
Simple solution would be to wrap the old-school stuff in the #else of #ifdef __cplusplus.  That way, the modern folks can have a well-behaved compiler-driven solution, and people who for some reason like C *and* Arduino, can have something that works.
I agree this is a solution. I would like to share this thought:
This solution will create situations where code works  in one situation and it doesn't in another. Newbies will not realize they moved their code from C++ to C (or the other way around) and will be completely puzzled. At that point in time there will only be a very small number of people who still know macro behavior and the specific Arduino implementation.
And then I ask myself (without implying an answer) What is worse? A commonly known drawback with little consequences or a rare unknown drawback with little consequences?

Best regards
Jantje
Logged

Do not PM me a question unless you are prepared to pay for consultancy.
Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


The code in Reply #7 is out.  It requires both parameters to be the same datatype.  New users have enough problems with datatypes.  Forcing them to learn typecasting makes the pain even worse.

The code in Reply #9 is out.  It does not compile with the GCC version that ships with Arduino nor with the latest WinAVR.

The code in Reply #11 has the same problem as the code in Reply #7.  

Which leaves the macro in Reply #13 and inline functions.  abs works very nicely as an inline function.  min and max not so much (too many combinations).  At this point, the only one left standing is the macro in reply #13.


A few points of interest: The code generation varies a bit and is not consistent.  Sometimes the "old" macro produces slightly better code.  Sometimes the template does.  Sometimes the "new" macro does.  Basically, all the solutions have at least one code generation quirk.  The random function appears to include an exception handler stack frame for some reason (lots of unnecessary code).  The round macro fails to work correctly for values past ±8388609.  The GCC / Libc round function works correctly.
« Last Edit: May 28, 2012, 05:07:34 pm by Coding Badly » Logged

Offline Offline
Full Member
***
Karma: 2
Posts: 196
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you don't mind my asking:

Why are these macros defined at all?
Isn't it more difficult to have to remember the "gotchas" of working with macros than it is to write your own code for these things when you need it?
We're not talking about anything fancy here. I mean, how hard is it to write something like this? x = (y>=0?y:-y);

As for squaring, is there any reason for the compiler not to handle y = pow(x,2) by using the obvious optimization?
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


There is no point contemplating why they exist.  There is a non-zero number of users who have used them so they cannot be removed.
Logged

Seattle, WA
Offline Offline
God Member
*****
Karma: 8
Posts: 673
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

And if they annoy you, you can always #undef them out so they don't annoy again.
Logged


South Texas
Offline Offline
Edison Member
*
Karma: 8
Posts: 1023
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A problem with implementing them as a function is STACK USAGE - Will they use more stack space (only 2K RAM, remember?) as a function or as a macro?

Stack is much more limited than is program memory. While it might be good to optimize for FLASH usage, you must not forget limited RAM.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A problem with implementing them as a function is STACK USAGE - Will they use more stack space (only 2K RAM, remember?) as a function or as a macro?

For normal# functions with a few bytes of parameters (like min(int,int)) only the return address is pushed on the stack (two bytes).  The parameters are passed in registers.

For inline functions the code is inserted at the call-point so not even the return address is pushed.

Quote
Stack is much more limited than is program memory. While it might be good to optimize for FLASH usage, you must not forget limited RAM.

In terms of SRAM usage, there is essentially no difference in the choices discussed here.  The optimizer occasionally makes a minor mistake leading to one or two bytes unnecessarily being pushed but that behaviour seems to be independent of the implementation.


# As opposed to inline functions.
Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 53
Posts: 1799
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't see a real problem with using the macros I just wish the reference would say they are macros and also have an example of how the usage may fail so people can avoid it without having in-depth c/c++ knowledge.

The biggest drawback of these macros is the inability to use those macro names in your own code. A range class for example would benefit from members named min & max over something like LowVal and HighVal for example.
Logged


South Texas
Offline Offline
Edison Member
*
Karma: 8
Posts: 1023
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


The biggest drawback of these macros is the inability to use those macro names in your own code. A range class for example would benefit from members named min & max over something like LowVal and HighVal for example.

That's a problem with any language except for Forth. Reserved keywords and such are an issue with any language. Only Forth allows you to redefine a WORD without damaging the code that used the old version.
Logged

Pages: 1 2 [3]   Go Up
Jump to: