int to char cast, strange behavior

0

Consider the following:

unsigned int  i1 = 0xFFFFFFFF;
unsigned char c1 = i1;
char          c2 = i1;

printf("%x\n", i1);       // 0xFFFFFFFF as expected
printf("%x\n", c1);       // 0xFF as expected
printf("%x\n", c2);       // 0xFFFFFFFF ????
printf("%d\n", c1 == c2); // false ????

I know, one should not assign an int to a char. Anyway, look how c2 seems to be storing more than a byte. What I expected was a copy of the "less significant byte" of n1 into c2. Am I wrong to assume this? Is there no copy at all? Why does the behavior of unsigned char differs from char?


I actually found this in a very concrete situation while using gethostbyname(). It returns a struct which contains a field char *h_addr storing an ipv4 address (four 8 bit long numbers). I wanted to print the ip address as numbers but got abnormally large results.


I know a workaround, masking with i1 & 0xFF works but I would like to understand the issue.

c
char
printf
implicit-conversion
integer-promotion
asked on Stack Overflow Jan 29, 2021 by Mathis Brossier • edited Jan 29, 2021 by Vlad from Moscow

1 Answer

1

In your system the type char behaves as the type signed char.

After this assignment

char          c2 = n1;

Note: It seems there is a typo and you mean

char          c2 = i1;

the variable c2 has the value 0xff that is -1.

In this call

printf("%x\n", c2);

the argument expression c2 is converted to the type int propagating the sign bit due to the integer promotions. And this value is outputted according to the format %x.

Pay attention to that you need to write

printf( "%x\n",( unsigned int ) c2 );

because the conversion specifier x expects an object of the type unsigned int.

If you want to get the expected by you result you need output the objects as objects of character types using conversion modifier hh. For example

#include <stdio.h>

int main(void) 
{
    unsigned int  i1 = 0xFFFFFFFF;
    unsigned char c1 = n1;
    char          c2 = n1;

    printf( "%x\n", i1 );
    printf( "%hhx\n", c1 );
    printf( "%hhx\n", c2 );
}

The program output is

ffffffff
ff
ff

Also it seems you made a typo and wrote

printf("%d\n", n3 == n2);

instead of

printf("%d\n", c1 == c2);

If so then again the operands of the comparison operator are implicitly converted to the type int due to the integer promotions. As the operand c1 has the type unsigned char then it is converted to the value 0x000000FF while the operand c2 as it stores a negative value is converted to the value 0xFFFFFFFF. So the result values are not equal to each other.

answered on Stack Overflow Jan 29, 2021 by Vlad from Moscow • edited Jan 29, 2021 by Vlad from Moscow

User contributions licensed under CC BY-SA 3.0