-1

I'm confused. Why in this program a gives me 0xFFFFFFA0 but b gives me 0xA0? It's weird.

#include <stdio.h>
int main()
{
    char a = 0xA0;
    int b = 0xA0;

    printf("a = %x\n", a);
    printf("b = %x\n", b);
}
delxa
  • 99
  • 1
  • 8
  • 2
    Because the `char` is `signed` and so `0xA0` is negative. – Weather Vane Mar 24 '18 at 18:03
  • No reason for confusion. Since you did not specify, the compiler is using its default signedness for `int` and `char`. – Jongware Mar 24 '18 at 18:03
  • 1
    The `printf` format specifier `%x` does not know it was passed an `int` (second case) or a `char` which was promoted to `int` (first case), it works with the data it was given, in the context of expecting `unsigned int`. – Weather Vane Mar 24 '18 at 18:05
  • Possible duplicate of [Is char signed or unsigned by default?](https://stackoverflow.com/questions/2054939/is-char-signed-or-unsigned-by-default) – Jongware Mar 24 '18 at 18:05

2 Answers2

2

Default type of a is signed in char a = 0xA0; and in any signed data type whether its char of int you should be careful of sign bit, if sign bit is set means number will be negative and store as two's compliment way.

char a = 0xA0; /* only 1 byte for a but since sign bit is set, 
              it gets copied into remaining bytes also */

a  =>                                     1010 0000
                                          |
                                        this sign bit gets copied
        1111 1111  1111 1111  1111 1111   1010 0000
         f    f      f   f     f    f      A    0  

In case of int b = 0xA0; sign bit(31st bit) is 0 so what ever it contains i.e 0xA0 will be printed.

Achal
  • 11,821
  • 2
  • 15
  • 37
0

Let's take this step-by-step.


char a = 0xA0;

0xA0 in an integer constant with a value of 160 and type int.

In OP's case, a char is encoded like a signed char with an 8-bit range. 160 is more than the maximum 8-bit char and so assigning an out-of-range value to a some signed integer type is implementation defined behavior. In OP's case, the value "wrapped around" and a took on the value of 160 - 256 or -96.

// Try
printf("a = %d\n", a);

With printf() (a variadic function), char a it passed to the ... part and so goes though the usual integer promotions to an int and retains the same value.

printf("a = %x\n", a);
// is just like
printf("a = %x\n", -96);

printf("a = %x\n", a);

With printf(), "%x" expect an unsigned or an int with a value in the non-negative range. With int and -96, it is neither and so the output is undefined behavior.

A typical undefined behavior is this case is to interpret the passed bit pattern as an unsigned. The bit pattern of int -96, as a 32-bit int is 0xFFFFFFA0.


Moral of the story:

  1. Enable a compile warnings. A good compiler would warn about both char a = 0xA0; and printf("a = %x\n", a);

  2. Do not rely on undefined behavior.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256