Assuming a machine with sizeof(int) == 4
and CHAR_BITS == 8
(so sizeof(int) > sizeof(uint16_t)
, the C standard stipulates that:
crc = crc ^ (uint16_t)data << 8;
undergoes the 'usual arithmetic conversions', and is treated more or less as though you'd written (the 8
is already an int
so it doesn't get converted):
crc = (uint16_t)( ((int)crc) ^ (((int)((uint16_t)data)) << 8) );
And it is the assignment of the int
result of the xor operator in the assignment to the uint16_t
variable crc
that triggers (accurately) the warning.
Similar remarks apply to each of the two other lines marked.
If you were working on a machine where sizeof(int) == sizeof(uint16_t)
, you would not be getting the warnings in the first place.
6.3.1.8 Usual arithmetic conversions:
¶1 Many operators that expect operands of arithmetic type cause conversions and yield result
types in a similar way. The purpose is to determine a common real type for the operands
and result. For the specified operands, each operand is converted, without change of type
domain, to a type whose corresponding real type is the common real type. Unless
explicitly stated otherwise, the common real type is also the corresponding real type of
the result, whose type domain is the type domain of the operands if they are the same,
and complex otherwise. This pattern is called the usual arithmetic conversions:
And 6.3.1.1 Boolean, characters, and integers says:
¶2 … If an int
can represent all values of the original type (as restricted by the width, for a
bit-field), the value is converted to an int
; otherwise, it is converted to an unsigned
int
. These are called the integer promotions.58) All other types are unchanged by the
integer promotions.
58) The integer promotions are applied only: as part of the usual arithmetic conversions, to certain
argument expressions, to the operands of the unary +
, -
, and ~
operators, and to both operands of the
shift operators, as specified by their respective subclauses.
§6.3.1.1¶1 defines 'rank' in excruciating detail, but basically bigger types have a higher rank than smaller types (so long
has a higher rank than signed char
).
You can then find the specifications for the various operators:
6.5.7 Bitwise shift operators:
Each of the operands shall have integer type.
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.
6.5.11 Bitwise exclusive OR operator:
Each of the operands shall have integer type.
The usual arithmetic conversions are performed on the operands.
6.5.16 Assignment operators
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment,111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion.
111) The implementation is permitted to read the object to determine the value but is not required to, even
when the object has volatile-qualified type.
6.5.16.1 Simple assignment:
In simple assignment (=
), the value of the right operand is converted to the type of the
assignment expression and replaces the value stored in the object designated by the left
operand.