6
main()
{
    char i=255;
    printf("\n%x\n",i);
}

output:ffffffff

main()
{
    u_char i=255;
    printf("\n%x\n",i);
}

output:ff

What is happening here? Kindly explain the output to me with some good links. This is a very basic thing I guess and I am getting really confused...

pflz
  • 1,891
  • 4
  • 26
  • 32

4 Answers4

10

What you are seeing here is caused by two things:

  • 255 does not fit in the range of char (note that it is implementation-defined whether char is equivalent to signed char or unsigned char, but evidently on your platform it is signed char). The resulting behaviour is implementation-defined, but typically it will wrap round and become -1; see two's complement.
  • integer promotion, because printf() is a variable-argument function. Integral-type arguments (like char) are automatically promoted to int.

So printf() sees an int with a value of -1, and prints its hexadecimal representation accordingly.

For the unsigned case, there is no wrap-around. printf() sees an int with a value of 255, and prints its hexadecimal representation accordingly (omitting the leading zeros).

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • Could you throw some more light on that please? Why is it getting promoted? 255 is 11111111 in binary, so 2's comp will be 000000001. So should it not print 0f? – pflz Apr 17 '11 at 18:43
  • 2
    @Naman: It is getting promoted because that is what the C standard says should happen. When I say "two's complement", I mean "two's complement arithmetic", not "the two's complement of the value". – Oliver Charlesworth Apr 17 '11 at 18:46
4

The C compiler has to expand the value passed to printf (this is called "promotion"), because printf is a variadic function (it can be called with differing arguments). For values of type char, the promoted value is of type int. Since your compiler's char type seems to be signed, the promoted value is sign extended. In binary:

char i = 255           // or: 11111111 in binary
int promoted_i = -1    // or: 11....11111 (usually, 32 or 64 ones)

In the unsigned case, no sign-extension happens:

char u = 255           // or: 11111111 in binary, same as above but with different interpretation
unsigned int pu = i    // or: 00....0011111111 (8 ones, preceded by the appropriate number of zeroes) 
Dirk
  • 30,623
  • 8
  • 82
  • 102
0

char i = 255; invokes implementation-defined behavior by converting a value to a signed type into which it does not fit (assuming char is only 8 bits and plain char is signed, both of which are also implementation-specific.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

When you set an 8-bit signed variable to the value 255, which it can't hold, it seems in this case it sets the negative (high-end) flag to 1, so the value would be -1 if it were signed, but then it gets converted to an integer -1 which is ffffffff.

Ry-
  • 218,210
  • 55
  • 464
  • 476