Abs(-32768) behaves differently if argument is an array variable?

I'm having trouble putting this problem into words; I think the code and comments below should illustrate it clearly. The last print statement causes the behavior that I don't understand.

abs(-32768) equates to -32768 (for a signed integer), because +32768 doesn't fit.

So why does IF(abs(-32768) < 0) equate to FALSE, but only if -32768 is stored in an array?

I've tried this on an inventr.io Hero board and on a Sparkfun Redboard Plus, which are both treated as Arduino Unos.

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

void loop() {
  static const signed int NOTARRAY = -32768;
  Serial.println("Value NOT stored in array:");
  Serial.println(NOTARRAY); //This prints -32768
  Serial.println(abs(NOTARRAY)); //This also prints -32768
  Serial.println((NOTARRAY < 0) ? "<0" : ">=0");//This prints "<0"
  Serial.println((abs(NOTARRAY) < 0 ) ? "<0" : ">=0"); //This also prints "<0"

  static const signed int ARRAY[1] = { -32768 };
  Serial.println("Value IS stored in array:");
  Serial.println(ARRAY[0]); //This prints -32768
  Serial.println(abs(ARRAY[0])); //This also prints -32768
  Serial.println((ARRAY[0] < 0) ? "<0" : ">=0"); //This prints "<0"
  Serial.println((abs(ARRAY[0]) < 0 ) ? "<0" : ">=0"); //But THIS prints ">=0", even though ARRAY[0] == abs(ARRAY[0])

  while(true){}
}

You are in the realm of undefined behavior. There are quite a number instances of "undefined behavior" with the C/C++ programming languages, and you have to learn to live with them.

Do you agree that it makes no sense to compute abs(-32768), using 16 bit integer math?

https://cplusplus.com/reference/cstdlib/abs/

Exceptions (C++)

No-throw guarantee: this function throws no exceptions.

If the result cannot be represented by the returned type (such as abs(INT_MIN) in an implementation with two's complement signed values), it causes undefined behavior.

I did read that it is undefined behavior in C++.

But I also read that Arduino uses a different definition (abs(x) where x < 0 returns -x), which should not be undefined even for x = -32768. That was just on the forum here though, so it may not be accurate.

It would be great if you knew where I could find an "accurate" definition of Arduino's abs() function.

So… what should abs(-32768) be?

a7

I don't know the reason why Arduino defined their own function.

Why do you think Arduino's version solves the problem?

I make sure to never divide by zero, and now, I will add to my mental DON'T list to avoid computing abs(-32768).

Actually I think I misread the other posts that I was looking at; I don't think that Arduino wrote their own function, and I think you are correct that this is undefined behavior.

(They should really make a note of this on the reference page).

I was under the impression that it was defined in the Arduino language to be -32768 in order to avoid undefined behavior. But I now think that I was mistaken.

They did, as a macro. See post #7 above. But I have no idea why.

Yes, I see. I was thinking that there was no problem trying to store +32768 and letting it overflow, and not considering that it couldn't be calculated in the first place. Thank you.

Oh, I see. Well even with that in mind, I still think you're correct that this is undefined behavior, as Delta_G illustrated. Thank you for your help.

As an aside, the Reply button in this forum also does not work the way that I expected. I hope whoever finds this in the future doesn't mind reading my replies piled up at the bottom of the thread.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.