Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C bitwise negation creates negative output: [duplicate]

I am trying REALLY hard to flip the bits in a C int variable. I am doing it like so:

input = 15;

input = ~input;

printf("%d", input);

BUT IT ALWAYS SHOWS UP as -16. It should be 0! if 15 is written as 1111, why is it returning 10000?! This is maddening! Can somebody PLEASE help me!?

like image 850
Mizmor Avatar asked Aug 23 '12 03:08

Mizmor


3 Answers

Since int on your system is most likely a 32-bit number, all bits are flipped, including the ones that were insignificant zeros in the original number:

00000000000000000000000000001111

becomes

11111111111111111111111111110000

This is a negative number: the most significant bit of 15 is zero, so it becomes 1 when flipped.

If you would like to keep only the bits of the original number, you need to mask with all ones in the significant positions of the number, like this:

printf("%d\n", input & 0xF);

ANDing with 0xF "cuts off" all bits except the last four.

like image 143
Sergey Kalinichenko Avatar answered Oct 12 '22 16:10

Sergey Kalinichenko


This is occurring because input is comprised of more than four bits. If we assume that input is a signed char, with 8 bits (or one byte), then:

input == 15 == 0x0F == 0b00001111

As you can see, the 4 more significant bits of input are all 0. After a bitwise NOT operation (~), we have:

~input == -16 == 0xF0 == 0b11110000

The four bits that used to be zero are now ones, and the ones are now zeros. The most significant bit in a signed variable determines its sign (0 being positive and 1 being negative). Thus, by flipping the bits the sign has been reversed. The negative number may be read as:

1      1     1     1     0     0     0   0
-128 + 64  + 32  + 16  + 0   + 0   + 0 + 0

which resolves to the -16 that was printed.

If your homework is to zero a variable using the bitwise NOT, try declaring input as an unsigned char to avoid having to worry about the sign bit. Then, set input to 255, the highest value an 8 bit variable can hold (0xFF or 0b11111111).

like image 35
Paul Poulsen Avatar answered Oct 12 '22 17:10

Paul Poulsen


15 is of type int. Depending on how big int is, the representation of 15 ends in 1111, but it starts with a bunch of 0s.

The ~ operator flips all the bits; the 1s (4 of them) become 0s, and the 0s (N-4 of them) become 1s.

like image 26
Keith Thompson Avatar answered Oct 12 '22 15:10

Keith Thompson