0

Please help me to understand the output for the program:

int main()
{
    char a = 0x99;
    printf("%02x\n", a);
    return 0;
}

Output:

ffffff99

Why is the output like that?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
manikanta
  • 121
  • 8

3 Answers3

4

There are several factors at play. For one thing, on your computer, plain char is a signed type, not an unsigned type. For another, arguments to a variadic function like printf() undergo integer promotion rules, so your char is converted to int, and because it is signed, 0x99 as a char is a negative quantity, so it gets sign-extended to 0xFFFFFF99, and hence gets printed like that.

To get the result you expect, use one of:

printf("%02x", (unsigned char)a);
printf("%02x", a & 0xFF);
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

If your goal is to print hex value, you need to declare variable as uint8_t That is basically a byte and just print it as below

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    uint8_t a=0x99;
    printf("%x",a);
}
0

Read below for integer promotion.

If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

In your case applies rule 3, becouse printf expect unsigned int and you give signed char.

Martin Chekurov
  • 733
  • 4
  • 15
  • Section 6.5.2.2 Function calls is more relevant: _If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type. The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments._ – Jonathan Leffler Apr 25 '17 at 14:31
  • It (6.5.2.2) also defines 'default argument promotions': _If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions._ – Jonathan Leffler Apr 25 '17 at 14:34
  • And section 6.3.1.1 defines 'integer promotions': _If an `int` can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an `int`; otherwise, it is converted to an `unsigned int`. These are called the integer promotions. All other types are unchanged by the integer promotions. The integer promotions preserve value including sign. As discussed earlier, whether a ‘‘plain’’ `char` is treated as signed is implementation-defined._ – Jonathan Leffler Apr 25 '17 at 14:38
  • There's also a footnote 58 saying: _The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary `+`, `-`, and `~` operators, and to both operands of the shift operators, as specified by their respective subclauses._ – Jonathan Leffler Apr 25 '17 at 14:38