2

I came across this question. What is the output of this C code?

#include <stdio.h>

    int main()
    {
        unsigned int a = 10;
        a = ~a;
        printf("%d\n", a);
    }

I know what tilde operator do, now 10 can be represented as 1010 in binary, and if i bitwise not it, i get 0101, so i do not understand the output -11. Can anyone explain?

NameSake
  • 53
  • 5

3 Answers3

4

The bitwise negation will not result in 0101. Note that an int contains at least 16 bits. So, for 16 bits, it will generate:

 a = 0000 0000  0000 1010
~a = 1111 1111  1111 0101

So we expect to see a large number (with 16 bits that would be 65'525), but you use %d as format specifier. This means you interpret the integer as a signed integer. Now signed integers use the two-complement representation [wiki]. This means that every integers where the highest bit is set, is negative, and furthermore that in that case the value is equal to -1-(~x), so -11. In case the specifier was %u, then the format would be an unsigned integer.

EDIT: like @R. says, %d is only well defined for unsigned integers, if these are in the range of the signed integers as well, outside it depends on the implementation.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • I just read the article. Makes sense. I am just trying to understand how the output is -11. Give me a minute, and I ll accept the answer once i understand – NameSake Dec 11 '17 at 23:11
  • i think you mean 'SO -11' – pm100 Dec 11 '17 at 23:12
  • The choice of `%d` causes undefined behavior. `%d` can only be used with an unsigned argument when the value of the argument is in the range of `signed int`. Here, it's not. – R.. GitHub STOP HELPING ICE Dec 11 '17 at 23:24
  • @EricPostpischil: I'm not sure what you're trying to say. `va_arg` has equivalent language that the signedness can mismatch if the value fits. Strictly speaking, `printf` does not use `va_arg` but is specified on its own and does not include such an exception, but it seems to be generally agreed that this is just an oversight and not intentional; see my related question: https://stackoverflow.com/questions/4664100/does-printfx-1-invoke-undefined-behavior – R.. GitHub STOP HELPING ICE Dec 12 '17 at 02:44
  • Regarding the answer's edit: "depends on the implementation" suggests that the behavior is implementation-defined or unspecified, but it's outright undefined. – R.. GitHub STOP HELPING ICE Dec 12 '17 at 02:45
  • @R..: Ah, never mind, 6.5.2.2 6 applies only “If the expression that denotes the called function has a type that does not include a prototype.” – Eric Postpischil Dec 12 '17 at 03:45
3

It's undefined behaviour, since "%d" is for signed integers; for unsigned ones, use "%u".

Otherwise, note that negative values are often represented as a two's complement; So -a == (~a)+1, or the other way round: (~a) == -a -1. Hence, (~10) is the same as -10-1, which is -11.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
1

The format specifier for an unsigned decimal integer is %u. %d is for a signed decimal integer.

printf("%d\n", a) is interpreting a as a signed int. You want printf("%u\n", a).

Galen
  • 1,307
  • 8
  • 15