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.
a
is anunsigned char
, a type with a range that can be represented by anint
. Soa
gets promoted to anint
. Assuming 32-bit wideint
s and two's complement:310 =
0000 0000 0000 0000 0000 0000 0000 0011
2~310 =
1111 1111 1111 1111 1111 1111 1111 1100
2The result interpreted as
signed int
is negative because the most significant bit, the sign bit, is set.Convert to decimal:
1111 1111 1111 1111 1111 1111 1111 1100
2¬
0000 0000 0000 0000 0000 0000 0000 0011
2+
0000 0000 0000 0000 0000 0000 0000 0001
2────────────────────────────
0000 0000 0000 0000 0000 0000 0000 0100
201002 = 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
char
could besigned
! A cast to (possiblysigned
)char
would 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
~a
is anint
eger, it is not the correct type for the format specifieru
andThe fprintf function (§7.19.6.1/9):
1) ISO/IEC 9899/Cor3:2007 aka C99:TR3 aka C99