C compiler performs integer promotions before executing the shift.
Rule 6.3.1.1 of the standard says:
If an
intcan 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.