I was wondering of the case in subtracting unsigned variables, if the case variable 1 is less than variable 2.
The reason for this is that in the case of using micros() and doing the math of subtraction, and then micros() has overflowed.
Then if there is no typecast for the subtraction operation, then the Arduino will treat them as signed variables and the result will have the -ve sign.
For example;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
uint8_t a = 1;
uint8_t b = 8;
Serial.println((uint8_t)(a-b));
}
void loop() {
// put your main code here, to run repeatedly:
}
So, my question now, is that if I didn't do the typecast, will the Arduino treat the typecast result as the non-typecast one ?
Something odd with the print() function. If a and b are declared as uint16_t or uint32_t, then the result prints as a large positive number, as expected, while with uint8_t the result prints as a negative number.
The result of Serial.print depends on how the function is overloaded, and you would have to look at the Arduino core code to see what the possibilities are. There are known bugs (or features) associated with printing 32 bit integer variables (at least, on AVR Arduinos), and I would not be surprised to learn about others.
I'm guessing that your real question has to do with micros() or the like overflowing.
If so, what is the question?
I'm guessing that your real question has to do with micros() or the like overflowing.
If so, what is the question?
My question is that why even when I declared the variables as uint8_t the result is negative ? I must typecast.
My other question is in this case if I decremented 1 - 8 for example and the result is -7, if I typecast the result it would be 249. My question at this point will the Arduino treat -7 like 249 ? will both numbers have the same output ?
And you're right, even in micros(), if the micros() overflowed and became counting from 0 and the last variable read is still a big number, for example:
uint32_t last_micros_read = 4294000000;
uint32_t period = 1000; // e.g. 1 milli second time interval
// so the usual time math would be
// in this case let's assume that micros() has overflowed and started counting from 0 and reach 100 for example
if(micros() - last_micros_read >= period){
}
so if we did the math the answer will be 100 - 4294000000 = -4293999900
so the answer is negative, and if we typecast the answer we will get: (uint32_t)(100 - 4294000000) = 967396
The Arduino program, when performing mathematical operations, strictly obeys the rules of the C/C++ programming language.
The output of Serial.print() sometimes defies expectations, due to oversights or coding errors in the Arduino core, or perhaps your misunderstanding of the math rules.
So take Serial.print() output with a grain of salt, as I do. It is far from perfect.
The problem is not with print(), but with the compiler promoting the uint8_t to int before doing the arithmetic. A bit of searching on google gets into promotion rules for C language, and having anything smaller than an int converted into an int before performing an operation such as subtraction. The smallest form of an int that can fully represent any value in a uint8_t is a signed int, so the promotion is to an int instead of an unsigned int.
Any unsigned integer of at least 16 bits works on an UNO.
uint8_t subtraction : -7
negative result
uint16_t subtraction : 65529
positive result
uint32_t subtraction : 4294967289
positive result
The same code, run on an UNO R4 WiFi gives a different output, because an int is 4 bytes instead of 2. (which might be a cause for some pre-existing code to suddenly have problems when run on an R4)
uint8_t subtraction : -7
negative result
uint16_t subtraction : -7
negative result
uint32_t subtraction : 4294967289
positive result
No, the subtraction and resulting answer should all be done using unsigned 32-bit integers, with the correct positive result of 967396, as long as the size of an integer is 32 bits or less on the processor you are using.