I get different results using the abs() function depending on the argument passed to it. In the code below line 18 gives a different result (-10) from line 24 (10). I expected line 27 to give the same as line 33.
Can someone please explain this to me?
Thank you, Dale Gloer
Serial.begin(115200);
Serial.println(" Started ") ;
unsigned int test;
int Atest;
int Ftest;
int eighty = 80;
int ninety =90;
/* test = ninety - eighty;
Serial.println(test);
Atest = abs(test);
Serial.println(Atest);
*/
Serial.println(" First try ");
test = eighty - ninety;
Serial.println(test);
Atest = abs(test); // this is line 18
Serial.println(Atest);
Serial.println(" Now the math ");
Ftest = ninety + Atest;
Serial.println(Ftest);
Serial.println(" Now the second try ");
Atest = abs(eighty - ninety); // this is line 24
Serial.println(Atest);
Serial.println(" Now the math ");
Ftest = ninety + Atest;
Serial.println(Ftest);
}
void loop()
{
}
First of all, an unsigned int can be negative. This only affects the internal representation of the value according to the language reference for int.
Quoting the relevant part:
" On the Uno and other ATMEGA based boards, unsigned ints (unsigned integers) are the same as ints in that they store a 2 byte value. Instead of storing negative numbers however they only store positive values, yielding a useful range of 0 to 65,535 ((2^16) - 1). "
Secondly reading the references for the abs() macro, while it appears that it is true that it is a macro, there is also a Function called abs() - defined in the language reference. There is also a way to disable the macro listed in one of the entries.
It is correct that there is a warning about using a function within a abs() call. I need to read more carefully and improve my understanding of what I read. On to making my code do what I need!
This is one of the reasons why macros are stupid to use compared to a proper function. Type safety! I quite like the constraints of a strongly typed language, thank you very much.
If you're not careful about type safety and using signed numbers when negatives are possible, you get weird this like (unsigned int)-1 > 0 being true.
In this case, the fact that abs() is a macro has nothing to do with the problem.
abs(x) expands to essentially:
if (x>0)
return x;
return -x;
if x is declared as an unsigned variable, the compiler will recognize the if statement as always TRUE, and will simplify the expression to just "return x"
I thought gcc would issue a warning for this sort of thing ("comparison is always true" or something like that), but:
apparently not. (I couldn't get it to happen, even in a test program outside of Arduino, with -Wall -Wextra)
I can't find the specific warning in the gcc documentation.
Arduino compiles typically disable most warnings anyway.