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.