Why does the complement behave differently through printf?
bitwise-operators, c, types, unsigned-char, variables
Solution
In this statement:
printf("%d",~c);
the `c` is converted to `int`1 type before `~` (bitwise complement) operator is applied. This is because of integer promotions, that are invoked to operand of the `~`. In this case an object of `unsigned char` type is promoted to (signed) `int`, which is then (after `~` operator evaluation) used by `printf` function, with matching `%d` format specifier.
Notice that default argument promotions (as `printf` is a variadic function) does not play any role here, as object is already of type `int`.
On the other hand, in this code:
unsigned char c = 4, d;
d = ~c;
printf("%d", d);
the following steps occur:
- `c` is a subject to integer promotions because of `~` (in the same way, as described above)
- `~c` rvalue is evaluated as (signed) `int` value (e.g. `-5`)
- `d=~c` makes an implicit conversion from `int` to `unsigned char`, as `d` has such type. You may think of it as the same as `d = (unsigned char) ~c`. Notice that `d` cannot be negative (this is general rule for all unsigned types).
- `printf("%d", d);` invokes default argument promotions, thus `d` is converted to `int` and the (nonnegative) value is preserved (i.e. the `int` type can represent all values of `unsigned char` type).
1) assuming that `int` can represent all values of the `unsigned char` (see T.C.'s comment below), but it is very likely to happen in this way. More specifically, we assume that `INT_MAX >= UCHAR_MAX` holds. Typically the `sizeof(int) > sizeof(unsigned char)` holds and byte consist of eight bits. Otherwise the `c` would be converted to `unsigned int` (as by C11 subclause §6.3.1.1/p2), and the format specifier should be also changed accordingly to `%u` in order to avoid getting an UB (C11 §7.21.6.1/p9).
Problem
I was reading a chapter on bitwise operators, I came across 1's complement operator program and decided to run it on Visual C++. ``` int main () { unsigned char c = 4, d; d = ~c; printf("%d\n", d); } ``` It gives the valid output: `251` Then instead of using `d` as a variable to hold the value of `~c`, I decided to directly print the value of `~c`. ``` int main () { unsigned char c=4; printf("%d\n", ~c); } ``` It gives the output `-5`. Why didn't it work?