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?
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.
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.
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.
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.