# Help me understand, data types and multiplication

Why is adding the parentheses causing this behavior?

I know they don't do any difference in this case for the mathematical equation just curious why.

``````uint8_t a = 10;

uint32_t b,c;

b = (uint32_t) 5000*10*a+5000;
c = (uint32_t) (5000*10*a)+5000;

Serial.println(b); // Prints 505000. I expect this.
Serial.println(c); // Prints 4294948008. Not this.
``````

Try the following codes and teach yourself why the right hand operands should have 'explicit' 'castings'.

``````uint8_t a = 10;

uint32_t b, c;
void setup()
{
Serial.begin(9600);
b = (uint32_t) 5000 * (uint32_t)10 * (uint32_t)a + (uint32_t)5000;
c = (uint32_t) ((uint32_t)5000 * (uint32_t)10 * (uint32_t)a) + (uint32_t)5000;

Serial.println(b); // Prints 505000. I expect this.
Serial.println(c); // Prints 505000. [u]Prints 4294948008. Not this.[/u]

}

void loop()
{

}
``````

Thank you!

It is a combination of what is usually called “operator precedence” and so called “the usual arithmetic conversions”.

The usual arithmetic conversions basically say that when you supply two values of the same type to a binary operator, the calculation is performed in the domain of that type. But if you mix values of two different types in a binary operator, the calculation is performed in the domain of the larger type (and unsigned wins over signed).

In C and C++ the cast operator `(uint32_t)` has very high precedence - higher than binary `*` operator. This means that the first expression is seen by the compiler as

``````b = ((uint32_t) 5000) * 10 * a + 5000;
``````

The value `5000` is immediately converted to `uint32_t` type. This type has range `[0, 2<sup>32</sup>)` on our platform. According to the usual arithmetic conversions, `5000` is then multiplied by `10` in the domain of `uint32_t` type, producing `50000`. After that it is multiplied by `a`, which is also `10`. The intermediate result is `500000`. After that `5000` is added to the intermediate result and the final value of `505000` is stored in `b`. Note that at all stages the intermediate result remains within the range of `uint32_t` type.

In the second expression you added parenthesis to change the grouping of operators and operands.

In the second expression the cast is no longer attached to `5000`. The second expression begins with a multiplication of `5000` and `10`. `5000` has type `int`, which has range `[-32768, 32767]` on our platform. You multiply it by `10`, which also has type `int`. This means that the calculations are performed in the domain of type `int`. The mathematical result is `50000`, which is already out of range for `int`. This is called signed arithmetic overflow. Signed arithmetic overflow triggers undefined behavior. After that the behavior of your expression is undefined and there’s no point in analyzing it further. You can regard that `4294948008` as nonsensical and generally unpredictable value - a garbage produced by undefined behavior.

Note that you don’t need specifically casts to make this expression behave as expected. This

``````b = 5000ul * 10 * a + 5000;
``````

will also follow the first scenario.

@OP

And you should acknowledge that this: 'Serial.println(c); // Prints 4294948008' is also correct as you have asked for it.

(1) You have asked Arduino UNO to compute this: 50001010.
By default, the 'processing buffer size' of Arduino UNO is '16-bit of type int'. So, the compiler will keep this: 0xA120 (lower 16-bit) of the result of 500010a (0x7A120).

(2) Then you have applied this cast: uint32_t which means that you have asked the compiler to expand the 'processing buffer size to 32-bit of type unsigned' and then keep the value A120 into it. The compiler will happily expand the 'processing buffer size' to 32-bit; A120 will be stored into lower 16-bit and the upper 16-bit will be populated by the sign bit of A120, which is 1 (A = 1010). Now, the temporary result is '1111 1111 1111 1111 A120 = FFFFA120. Now, add 5000 (0x1388) with it, and we are getting: 0xFFFFB4A8 which is an unsigned number as is evident from the data type (uint32_t) of c. Let us execute this command: Serial.println(c, DEC) and observe that the Serial Monitor shows 4294948008.

Thanks for the clearification! Much appriciated.

After reading this and watching the videos below I am beginning to understand. As I think of it, many times before I have encountered this problem but instead changed every variable in the calculation to the "biggest" in this case unint32_t. Now this will help me reduce code size and thats great.

nollieflip:
After reading this and watching the videos below I am beginning to understand.

Lots of incorrect information in those videos. Basically each video form the very first minutes - a stream of completely made up nonsense. They are just catastrophically bad.

Do yourself a favor a get a good book on C or C++. This is always a much better idea than watching garbage-grade videos on YouTube.

Montmorency:
In the second expression the cast is no longer attached to `5000`. The second expression begins with a multiplication of `5000` and `10`. `5000` has type `int`, which has range `[-32768, 32767]` on our platform. You multiply it by `10`, which also has type `int`. This means that the calculations are performed in the domain of type `int`. The mathematical result is `50000`, which is already out of range for `int`. This is called signed arithmetic overflow. Signed arithmetic overflow triggers undefined behavior. After that the behavior of your expression is undefined and there's no point in analyzing it further. You can regard that `4294948008` as nonsensical and generally unpredictable value - a garbage produced by undefined behavior.

4294948008 is not a nonsensical value at all; it is exactly what the OP has asked for. Please, see Post#4.

GolamMostafa:
4294948008 is not a nonsensical value at all; it is exactly what the OP has asked for. Please, see Post#4.

Yes it is, from the point of view of C++ and C languages. Both languages clearly and explicitly states that the behavior is undefined. This immediately means that the result of that expression (if it even produces any result) is nonsensical. End of story.

In your post #4 you are simply trying to pick apart code generated by some specific compiler with some specific settings under some specific undefined behavior conditions. Your analysis is correct, but it is still a pointless waste of time. Today the value is `4294948008`, tomorrow it might become `12345` just because compiler decided to handle it differently.

We already thoroughly covered the topic of undefined behavior to great extent in other threads. I see no reason to do it all over again.