Skip to content

The warnings in reference of min(), max() and abs() seem wrong #2602

Closed
@mikecat

Description

@mikecat

http://arduino.cc/en/Reference/Min

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

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

http://arduino.cc/en/Reference/Max

max(a--, 0); // avoid this - yields incorrect results

a--; // use this instead -
max(a, 0); // keep other math outside the function

http://arduino.cc/en/Reference/Abs

abs(a++); // avoid this - yields incorrect results

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

In these warnings, the values that should be passed to the functions will be different in the code to avoid and the code to use.

In C++ language, the increase operator used as suffix should return the value before adding one.
This behavior is also observed in Arduino, and when I ran this code on Arduino 1.0.6 and Arduino UNO R3, the numbers yielded by the three XXX_usage() methods were different from one another.

void setup() {
  Serial.begin(9600);
}

int my_min(int a, int b) {
  return a <= b ? a : b;
}

void print_data(int i, int a, int ret) {
  Serial.print("i = ");
  Serial.print(i, DEC);
  Serial.print(", a = ");
  Serial.print(a, DEC);
  Serial.print(", ret = ");
  Serial.print(ret, DEC);
  Serial.println();
}

void wrong_usage() {
  Serial.println("----- wrong usage");
  for (int i = 98; i <= 102; i++) {
    int a = i;
    int ret;
    ret = min(a++, 100);
    print_data(i, a, ret);
  }
}

void reference_usage() {
  Serial.println("----- reference usage");
  for (int i = 98; i <= 102; i++) {
    int a = i;
    int ret;
    a++;
    ret = min(a, 100);
    print_data(i, a, ret);
  }
}

void func_usage() {
  Serial.println("----- func usage");
  for (int i = 98; i <= 102; i++) {
    int a = i;
    int ret;
    ret = my_min(a++, 100);
    print_data(i, a, ret);
  }
}

void loop() {
  switch (Serial.read()) {
    case 'w':
      wrong_usage();
      break;
    case 'r':
      reference_usage();
      break;
    case 'f':
      func_usage();
      break;
  }
}

Outputs:

----- wrong usage
i = 98, a = 100, ret = 99
i = 99, a = 101, ret = 100
i = 100, a = 101, ret = 100
i = 101, a = 102, ret = 100
i = 102, a = 103, ret = 100
----- reference usage
i = 98, a = 99, ret = 99
i = 99, a = 100, ret = 100
i = 100, a = 101, ret = 100
i = 101, a = 102, ret = 100
i = 102, a = 103, ret = 100
----- func usage
i = 98, a = 99, ret = 98
i = 99, a = 100, ret = 99
i = 100, a = 101, ret = 100
i = 101, a = 102, ret = 100
i = 102, a = 103, ret = 100

In conclusion, I suggest that the code in warning should be written as this:

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

min(a, 100);
a++;            // use this instead - keep other math outside the function
max(a--, 0);   // avoid this - yields incorrect results

max(a, 0);     // use this instead -
a--;           // keep other math outside the function
abs(a++);   // avoid this - yields incorrect results

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Component: CoreRelated to the code for the standard Arduino APIComponent: DocumentationRelated to Arduino's documentation content

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions