No. You're confusing some language you just invented with C.
The operand of the shift operator is of type unsigned int.
"x <<= c" is exactly the same as "((int)x) << c"
It doesn't matter whether the promotion is explicit or implicit,
the semantics
are the same.
((char)x) = ((char)( ((int)((char)x)) << ((int)c) ) ) ::
((char)x) = ((char)( ((char)x) << ((int)c) ) )
if the shift count ((int)x) is semantically preserved.
thereby conditionally shifting left ((char)x) by ((int)c) if c is
less than
the smaller of it's shifted operand's or target's precision (both
being char
in this instance) or otherwise returning 0; is semantically
equivalent and
typically more efficient on smaller lightly pipelined machines without
needing to literally promote the shifted operand to int width.
(I believe)
Sorry, but you're incorrect. While it may be "logical" that shifting
a value left more bits than its size will give you zero, this is not
what C specifies. Further, as Paul B says, this behavior is often
not provided by the hardware, e.g. on those obscure x86 boxes. If
you want strictly defined behavior like this, use Java or another
similar language, and be prepared to pay the performance hit when
targeting a machine without semantics that match your expectations.
OTOH, when targeting hardware that does properly handle oversized
shift amounts, GCC should certainly perform this transformation.
-Chris