Running the following program display -4 while 252 is expected:
unsigned char a=3;
printf ("%d", ~a);
Why this code doesn't display 252?
I also tested the folowings according to the proposed answer:
printf ("%u", ~a);
displays: 4294967292
printf ("%hu", ~a);
displays: 65532
Why ~a doesn't return an unsigned char since a is an unsigned char?
My question is not what should I do to display 252 ? My question is Why 252 is not displayed?
In addition to the answer of @Someprogrammerdude, here are the relevant passages from The Book1):
Unary arithmetic operators (§6.5.3.3/4)
Arithmetic operands - Boolean, characters, and integers (§6.3.1.1):
Your Question:
Because integer promotions apply.
ais anunsigned char, a type with a range that can be represented by anint. Soagets promoted to anint. Assuming 32-bit wideints and two's complement:310 =
0000 0000 0000 0000 0000 0000 0000 00112~310 =
1111 1111 1111 1111 1111 1111 1111 11002The result interpreted as
signed intis negative because the most significant bit, the sign bit, is set.Convert to decimal:
1111 1111 1111 1111 1111 1111 1111 11002¬
0000 0000 0000 0000 0000 0000 0000 00112+
0000 0000 0000 0000 0000 0000 0000 00012────────────────────────────
0000 0000 0000 0000 0000 0000 0000 0100201002 = 0 × 23 + 1 × 22 + 0 × 22 + 0 × 22
= 1 × 22
= 410
= −410 (with the original sign)
~>
printf()prints-4.To get the desired result of 252 with your original code which uses
"%d"as format specifier, some casting would be needed:*)Thanks to chux who made me remember that
charcould besigned! A cast to (possiblysigned)charwould give the wrong result of -4.To get the same result without a cast, you could use the length modifier
hh:The fprintf function (§7.19.6.1/7)
The problem with your other attempts:
Since
~ais aninteger, it is not the correct type for the format specifieruandThe fprintf function (§7.19.6.1/9):
1) ISO/IEC 9899/Cor3:2007 aka C99:TR3 aka C99