Here's an program to help illustrate sign extension. Note that 0 - 127 (0 to 0111 1111) in hex shows as expected, because the sign bit is 0, so when going from 8-bit to 32-bit its extended with 0's (which show as blank in the hex). Once you get to 128 (1000 000) signed char, it becomes a negative number (-128), and it is sign-extended with 1's / F's.
unsigned signed hex binary
-----------------------------------------------------------
unsigned char: 127 127 7f 0111 1111
signed char: 127 127 7f 0111 1111
unsigned signed hex binary
---------------------------------------------------------------
unsigned char: 128 128 80 00000000 00000000 00000000 10000000
signed char: ... -128 ffffff80 11111111 11111111 11111111 10000000
Program:
#include <stdio.h>
void print(char c) {
unsigned char uc = c;
printf(" %15s %15s %15s\n", "unsigned", "signed", "hex");
printf("---------------------------------------------------------------\n");
printf("unsigned char: %15u %15i %15x\n", uc, uc, uc);
printf(" signed char: %15u %15i %15x\n\n", c, c, c);
}
void main() {
print(127);
print(128);
}
Unsigned char gets extended with 0's even when going over 127, because you've explicitly told it that its a positive number.
When printing the signed char, as a signed integer, you can see how sign-extending is preserving the value of -128.
(edit: added binary column to the example output, will include this in the program code later)