3

I have been looking for an answert to the following behavior when working with Arduino. But have not found anything, therefore I hope you will be able to support.

I define two int8_t variables vA and vB. vA is defined as e.g. 125 an vB as 31. If I first add them and assign to a int8_t variable vSum, then call Serial.println(vSum) the number -100 is printed as expected (since they overflow as 8 bit numbers).

Now, when i call Serial.println(vA+vB) the result is wrong (156). As far as I understand the Serial.println() would in this case cast the result of the sum to a signed int. I would have expected, though, that it still returns the correct answer.

My understanding is obviously wrong. Does anybody know why it behaves like this?

Here once again the code

int8_t vA =125;
int8_t vB =31;
int8_t temp;
temp = vA+vB;
Serial.println(temp);  // This works as expected
Serial.println(vA+vB); // this does not work

Thanks for your support!

Bert
  • 57
  • 6
  • Here is good answer for similar question (https://stackoverflow.com/questions/4814668/addition-of-two-chars-produces-int): https://stackoverflow.com/a/4814901/5132939 – Ihor Drachuk Nov 27 '20 at 09:43
  • Thanks for the link. Am I seeing what it says here: "1 An rvalue of type char, signed char, unsigned char, short int, or unsigned short intcan be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int. " - So because of the overflow, the casting sees that the addition will not fit into a signed 8 bit value and therefore "changes" it to an unsigned 8 bit value. Is this a correct understanding? – Bert Nov 27 '20 at 10:02
  • No, overflow doesn't change anything here. It's compiler's decision at compile-time. Some operations with char (int8_t, uint8_t) will convert it to int anyway – Ihor Drachuk Nov 27 '20 at 10:18

2 Answers2

3

It is not the Serial.println that casts the values. It's the arithmetic operation.

The return value of vA+vB is already a signed integer.

In one case you store it in a int8_t variable which results in -100.

In the other case you print the 156 that acutally resulted from that operation.

You would have to cast (vA+vB) to int_8 to print -100.

Serial.println(int_8(vA+vB));

Read this: https://en.cppreference.com/w/cpp/language/operator_arithmetic

If the operand passed to an arithmetic operator is integral or unscoped enumeration type, then before any other action (but after lvalue-to-rvalue conversion, if applicable), the operand undergoes integral promotion.

and this:

https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion

prvalues of small integral types (such as char) may be converted to prvalues of larger integral types (such as int). In particular, arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion, if applicable. This conversion always preserves the value.

Piglet
  • 27,501
  • 3
  • 20
  • 43
0

Thank you for your answers. I think I now understand the reason behind the problem!

Bert
  • 57
  • 6