The output of this program is -13. I have never fully understood ~ operator in C. Why does it give -13 as output? How to limit ~ operator to just 4 bits of a number?
<
The operator ~
is the logical not
in C, i.e. when applied to a integer it flips every single it of its binary representation. Note that defining a integer in simply as int
makes it unsigned integer. That means that the first it is used as a sign bit. Since negatives are defines as -a = ~a + 1
you can see that ~a = -a - 1
. If you want to flip only the last 4(or more generally the last k) bit of a int
you could do something like this
int k = 4;
int mask = (1 << k) - 1;
int b = a ^ mask;
The ~ operator acts as a binary NOT, that is, it flips all the bits in the number. Negative numbers in signed integers are stored as two's complement.
(12)10
in binary is (1100)2
The tilde is the bitwise complement operator which makes 1100
--> 0011
. However if you working on a 32 bit platform actually what we get is:
0000 0000 0000 0000 0000 0000 0000 1100
Whose bitwise complement is:
1111 1111 1111 1111 1111 1111 1111 0011
|
Now since the left most bit is for sign the number becomes negative. If you use unsigned int you will be able to understand better what is happening:
unsigned int a = 12;
a = ~a;
Will give:
1111 1111 1111 1111 1111 1111 1111 0011
Which is 4294967283
it's a bitwise operator (one's complement ) that works this way :
~00000101 // 5
=11111010 // 250
so the 1s become 0s and vise versa but in some cases the sign bit is activated and you'll get unexpected results
To limit the effect to a specified number of bits, just use bitwise masks, e.g.:
#include <stdio.h>
int main(void) {
int a = 16; /* 10000 in binary */
int b = ~a; /* Will interpret b as -17 in two's complement */
int c = (a & ~0xF) | (~a & 0xF); /* Will limit operator to rightmost 4 bits,
so 00000 becomes 01111, and c will become
11111, not 11...101111, so c will be 31 */
printf("a is %d, b is %d, c is %d\n", a, b, c);
return 0;
}
Outputs:
paul@local:~/src/c/scratch$ ./comp
a is 16, b is -17, c is 31
paul@local:~/src/c/scratch$