Why are characters with value above 127 "padded" with 1s to be 16 bits long, while ones with values 0-127 aren't?
On the AVR platform the char type happens to be signed, and it can
store numbers in the range [−128, +127]. Thus, when you write
char bar = 128;

You are asking to store in bar a number that does not fit. It then
gets reduced modulo 28 into the value that does fit, namely
−128. For the kind of manipulations you are trying to make, I would
recommend you use uint8_t instead of char.

it would be always safe (and not undefined behavior) if I did it as
follows

It is indeed safe, and the casts you use are needed to make it safe.