C compiler performs integer promotions before executing the shift.
Rule 6.3.1.1 of the standard says:
If an
int
can represent all values of the original type, the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions.
Since all values of unsigned char
can be represented by int
, 0x80
gets converted to a signed int
. The same is not true about unsigned int
: some of its values cannot be represented as an int
, so it remains unsigned int
after applying integer promotions.