It's about the interpretation that printf gives to the parameter you pass.
unsigned int x = 11;
printf("not x=%d", ~x);
During the function call the default argument promotions will pass ~x to printf as type unsigned int. The default argument promotions are applied due to va_args from the signature of printf.
Also, integer promotions are applied for computing the ~x -- from 6.5.3.3 Unary arithmetic operators:
The result of the ~ operator is the bitwise complement of its
(promoted) operand (that is, each bit in the result is set if and only
if the corresponding bit in the converted operand is not set). The
integer promotions are performed on the operand, and the result has
the promoted type. If the promoted type is an unsigned type, the
expression ~E is equivalent to the maximum value representable in that
type minus E.
So you pass an unsigned integer, but printf will cast it to int, as %d expects to find an int.