Signature behavior and unsigned characters when printing in C
I have compiled the following C program in Code :: Blocks 10.05 on Windows 7.
int main()
{
unsigned char a=-5;
signed char b=-5;
char c=-5;
printf("%d %d %d \n",a,b,c);
printf("%u %u %u \n",a,b,c);
}
I expected the next exit
251 -5 -5
251 251 251
I reasoned like that
-5 is represented as 1111 1011 in 2 Complement notation. Hence, 251 will be printed.
But I got the following result.
251 -5 -5
251 4294967291 4294967291
I know that 4294967291 is a 32-bit representation of 2-5.
But why is unsigned char a printed as 251 instead of 4294967291?
source to share
printf
is a variational function that calls (thanks to @TheParamagneticCroissant for the correction) integral arguments to be promoted to int or unsigned int. Which, in accordance with the standard promotion rules, will sign them accordingly. This leads to the fact that you get the results obtained after this promotion process.
You can use "%" PRIu8
8-bit unsigned "%" PRId8
for printing and 8-bit signature numbers instead . However, be careful that the arguments will continue to advance and then printf will omit them again according to the format specifier, which might still change that value, but I'm not sure about this from memory.
Also, char is not guaranteed to be 8 bits in C, better include the header <stdint.h>
and use the appropriate fixed width types.
The fixed version of your code would be like this:
#include <stdint.h>
int main()
{
uint8_t a=-5;
int8_t b=-5;
printf("%" PRId8 "%" PRId8 "\n", a, b);
printf("%" PRIu8 "%" PRIu8 "\n", a, b);
}
Note. I am not including the char equivalent since all fixed-width types have a definite sign, so there is no direct equivalent to char that has an undefined signature.
source to share
unsigned
integral types (including unsigned char
) work with modular arithmetic. For unsigned char
, that is, modulo UCHAR_MAX + 1
, where UCHAR_MAX
is an implementation-defined value in <limits.h>
with a typical value with most implementations 255
( 255
also the minimum value that the standard allows for UCHAR_MAX
). By adding 256
in -5
(i.e. to get the remainder between 0
and 255
for initialization a
in your code) explain why a
it matters 251
.
As for what any of the values ββare printing at all, the values ββare passed to the type int
when passed to printf()
. This promotion is not related to your format string, but this is what the format specifier expects %d
, so the values ββare printed as you can see.
source to share
@Vality is slightly wrong in his answer. Since it unsigned char
must contain at least 255 values, then if uint8_t exists, it CHAR_BIT
must be 8.
There is no reason to use nasty macros PRI
, just use this:
unsigned char a = -5;
signed char b = -5;
char c = -5;
printf("%hhd %hhd %hhd \n", a, b, c);
printf("%hhu %hhu %hhu \n", a, b, c);
source to share