Different types are created to tell the compiler how to "understand" the bit representation of one or more bytes. For example, say I have a byte which contains 0xFF
. If it's interpreted as a signed char
, it's -1; if it's interpreted as a unsigned char
, it's 255.
In your case, a
, no matter whether signed or unsigned, is integral promoted to int
, and passed to printf()
, which later implicitly convert it to unsigned char
before printing it out as a character.
But let's consider another case:
#include <stdio.h>
#include <string.h>
int main(void)
{
char a = -1;
unsigned char b;
memmove(&b, &a, 1);
printf("%d %u", a, b);
}
It's practically acceptable to simply write printf("%d %u", a, a);
. memmove()
is used just to avoid undefined behaviour.
It's output on my machine is:
-1 4294967295
Also, think about this ridiculous question:
Suppose sizeof (int) == 4
, since arrays of characters (unsigned
char[]){UCHAR_MIN, UCHAR_MIN, UCHAR_MIN, UCHAR_MIN}
to (unsigned
char[]){UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}
are same as
unsigned int
s from UINT_MIN
to UINT_MAX
, then what is the point
of using unsigned int
?