You have correctly figured out the content of the lower byte, i.e. 0xfe. However, there is more to what's actually happening here: when you write
if (c == 0xfe) {
...
}
you are comparing c, a char, to an int constant 0xfe. In this situation C rules require promoting char c to int for comparison. Since char is signed on your platform, 0xfe gets promoted to 0xfffffffe, which is why the comparison subsequently fails.
If you want to do the comparison in char type, cast 0xfe to char, like this:
if (c == (char)0xfe) {
...
}
Demo 1.
Unsigned characters, on the other hand, would give you no trouble with int promotion, because they fit nicely in an int:
unsigned char c = 127;
c<<=1;
if (c == 0xfe) { // No casting is necessary
...
}
Demo 2.
Note: The behavior of c <<= 1 is implementation-defined due to char overflow.