There are multiple issues in your question.
1. Possible typo
unsigned char t = 0xFC; // this is 252 in decimal, and -4 if it is unsigned char.
Most probably "if it is unsigned" is a typo, because unsigned numbers don't have a sign.
2. Misinterpretation of width field
printf("t: %d 0x%04X\n", t, t); // expecting result: 252 0xFC
The "0x" is not part of the conversion, and you tell printf()
to use at least 4 digits, filling up with zeroes. And so the actual output is correct:
t: 252 0x00FC
3. Additional unawareness of the system's width of int
printf("(signed char)t: %d 0x%04X\n",
(signed char)t,
(signed char)t); // expecting result: -4 0xFC
...
Why is the (signed char)t has 8 bytes? should it be 2 bytes as mentioned in so many C text books?
Apparently you know about integer promotion, but you don't know the width on an int
in your system, and it is 4 bytes. Books on standard C telling you that an int
has just 2 bytes are so old, you should drop them.
Additionally you are mixing "byte" and "hex digit". A single hex digit is 4 bits wide, to cover the range from 0x0=0b0000 to 0xF=0b1111. A byte is commonly 8 bits wide. So, the hex value "FFFFFFFC" has 8 digits, but these give 4 bytes.
You tell printf()
to use at least 4 digits, filling up with zeroes. Since the number to print has 8 digits, you get the correct output:
(signed char)t: -4 0xFFFFFFFC