3

I'm new to Arduino and C. This behavior is not what I'd expect:

Serial.begin(9600);
while ( ! Serial );

int myCount = 0;

for (int i=0; i<10; i++) {
    myCount = min( ++myCount, 8 );
    Serial.print( myCount );
    Serial.print( "  " );
}

I would expect:

1  2  3  4  5  6  7  8  8  8

But I get:

2  4  6  8  8  8  8  8  8  8

Why is my code counting by 2?

2
  • Because of the way the min() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results: arduino.cc/reference/en/language/functions/math/min – VE7JRO Dec 7 '18 at 7:11
  • 2
    if min is a macro such as #define min(a,b) ((a)<(b)?(a):(b)) think about what happens when you expand min( ++myCount, 8 ) .... you get ((++myCount)<(8)?(++myCount):(8)) - however, I didn't think it was a macro, so that's odd – Jaromanda X Dec 7 '18 at 8:23
5

Jaromanda X is indeed correct - min() is defined on line 92 of Arduino.h, thusly:

#define min(a,b) ((a)<(b)?(a):(b))

Therefore when the ++mycount is substituted for the a, it is in fact substituted twice, in both the (a)<(b) and the (a):(b), leading to the increment by 2, each time min(++mycount,8) is executed.

As VE7JRO mentions, as it is defined in this way, the reference for min(x,y) states:

Warning

Because of the way the min() function is implemented, avoid using other functions inside the brackets, it may lead to incorrect results

min(a++, 100);   // avoid this - yields incorrect results

min(a, 100);
a++;            // use this instead - keep other math outside the function

As the second example states, keep any incrementing outside of the min() macro.

Alternatively, I think that you could use the inline function to workaround this issue:

#undef min
inline int min(int a,int b) {return ((a)<(b)?(a):(b)); }

Because inline provides a real function call (with parameters) it avoids the use of macros and substitution, which gives rise to the issue that you encountered.

inline is a much better (safer) way to implement the functionality provided by macros, in many cases. For more information, see Inline functions in C++ or read a C++ reference.

2
  • 2
    The advantage of using a macro is it is type agnostic. You can use it with float, double, char, int, long, signed or unsigned, and it doesn't care. – Majenko Dec 7 '18 at 15:21
  • 2
    esp8266 has min() as template function. – Juraj Dec 7 '18 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.