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?

+3


source to share


4 answers


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.

+4


source


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.

+2


source


@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);

      

+1


source


Because it a

contains meaning 251

, not meaning -5

.

0


source







All Articles