The reason for the implicit conversion is due to the equivalency of the += operator with = and +.
From section 6.5.16.2 of the C standard:
3 A compound assignment of the form E1 op= E2 is equivalent to the simple assignment expression E1 = E1 op (E2), except that the lvalue
E1 is evaluated only once, and with respect to an
indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation
So this:
i += ((uint16_t)3);
Is equivalent to:
i = i + ((uint16_t)3);
In this expression, the operands of the + operator are promoted to int, and that int is assigned back to a uint16_t.
Section 6.3.1.1 details the reason for this:
2 The following may be used in an expression wherever an
intorunsigned intmay be used:
- An object or expression with an integer type (other than
intorunsigned int) whose integer conversion rank is less than or equal to
the rank ofintandunsigned int.- A bit-field of type
_Bool,int,signed int, orunsigned int.If an
intcan represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to anint;
otherwise, it is converted to anunsigned int. These are called the
integer promotions. All other types are unchanged by the integer
promotions.
Because a uint16_t (a.k.a. an unsigned short int) has lower rank than int, the values are promoted when used as operands to +.
You can get around this by breaking up the += operator and casting the right hand side. Also, because of the promotion, the cast on the value 3 has no effect so that can be removed:
i = (uint16_t)(i + 3);
Note however that this operation is subject to overflow, which is one of the reasons a warning is given when there is no cast. For example, if i has value 65535, then i + 3 has type int and value 65538. When the result is cast back to uint16_t, the value 65536 is subtracted from this value yielding the value 2, which then gets assigned back to i.
This behavior is well defined in this case because the destination type is unsigned. If the destination type were signed, the result would be implementation defined.