How do bitwise operators work in C?
bit manipulation - Bitwise Reduction Operators in C - Stack Overflow
bit manipulation - Bitwise operation |= in C - Stack Overflow
udp - C Programming - Bitwise operators and knowing when to utilize - Stack Overflow
Videos
Hey all! I got another beginner question. So, I'm learning about bitwise operators from this site. Here's what it says about the bitwise not:
Bitwise NOT is an unary operator that flips the bits of the number i.e., if the ith bit is 0, it will change it to 1 and vice versa. Bitwise NOT is nothing but simply the one’s complement of a number. Lets take an example.
N = 5 = (101)2
~N = ~5 = ~(101)2 = (010)2 = 2
So, ~5 = 2. Now, when I try this in C:
#include <stdio.h>
int main(void) {
int c = 5;
c = ~c;
printf("%d", c);
return 0;
}
The output of the above program is -6. What am I doing wrong?
In C, assuming unsigned or two’s complement, !~x or ~x == 0 serves as a bitwise AND; it is 1 if and only if each bit of x is 1.
!!x or x != 0 serves as a bitwise OR; it is 1 if any bit of x is 1.
The negations, not properly called NAND or NOR since they do not apply a NAND or NOR in a bitwise fashion but rather apply a NOT to the bitwise AND or OR, are simply !!~x or ~x != 0 and !x or x == 0.
There is no bitwise XOR in the operations specified by the C standard. GCC has __builtin_parity which can provide this.
The above apply to the full width of x. Narrower widths can be implemented by setting the extra bits to identity elements (1 for AND, 0 for OR and XOR).
There are no dedicated operators for this, however in most cases you can achieve the same result using bitwise operators and casting the result to a bool, which effectively is a single bit. For example:
- AND: bitwise invert, convert to bool, negate:
bool and_reduction_4_bits(int n) { return !(~n & 0b1111); // C23 adds binary literals } - OR: just convert to bool
bool or_reduction(int n) { return n; // works for any number of bits }
The tricky one is XOR reduction. This could be done if you have a way to count the number of bits set, and then just check if that number is odd. Some compilers provide a builtin popcount() function to do that. If not, you can create your own function using bit twiddling hacks.
- XOR: count bits, check if odd
bool xor_reduction(int n) { return popcount(n) & 1; }
That's not a question, that's a whole bunch. :)
- You use bitwise operators when you want to view a number as a collection of bits, rather than an integer. It's much easier to say "I want this bit-pattern shifted two bits to the left" than to create the mathematically equivalent operation. They're conceptually different; if you think of the number as bits, using a bit-operator makes more sense.
- The
& 0xffffmakes sure the value is 16 bits, by masking off all higher bits. This assumes the system'sunsigned longis at least 16 bits wide, which is a pretty safe assumption. The&(bitwiseAND) is often used for this purpose. Look at the truth table for logical conjunction and think "false is 0, true is 1" to see how this works. - The
&before the hexadecimal constant is C's bitwise AND operator, which is used to do the masking I describe above. Basically, for single-bit variablesa & b, the result is1if and only if bothaandbare 1. The operator applies this logic to each pair of bits in its input terms. - The
~operator is C's bitwise inversion, it "flips" the bits of its argument. It is commonly used to create masks.
Everything you're talking about has to do with operations on the bit level. For example "var >> num" shifts the var to the right by num (meaning it devides the var by 2^num). Also the ~var inverts the var at bit level (eg. if var = 5 in bit notation= 101 ----> ~var = 010)
Super beginner question, I apologize but I often see other people's see code and I see a lot of, 0xFE, ox00001, or >~ and I just don't understand what these are and why we need them. I google for bitwise operators and so far what I understand is that they operate on each bit of a byte and i guess & ands a 0/1, | ors >> shifts right and such. but why do we need these in actual coding environments where using these things is better than using normal variables.
also what are 0xFE called and where can I learn about them?
Remember that an XOR is the exactly same as NOT EQUALS and XNOR is exactly the same as EQUALS. So, the following will give you exactly what you want:
return !(x ^ y);
Two numbers are equal if there is no difference between them:
int equal(int x, int y){
return !(x-y);
}
Numbers can be expressed in binary like this:
3 = 000011
5 = 000101
10 = 001010
...etc. I'm going to assume you're familiar with binary.
Bitwise AND means to take two numbers, line them up on top of each other, and create a new number that has a 1 where both numbers have a 1 (everything else is 0).
For example:
3 => 00011
& 5 => 00101
------ -------
1 00001
Bitwise OR means to take two numbers, line them up on top of each other, and create a new number that has a 1 where either number has a 1 (everything else is 0).
For example:
3 => 00011
| 5 => 00101
------ -------
7 00111
Bitwise XOR (exclusive OR) means to take two numbers, line them up on top of each other, and create a new number that has a 1 where either number has a 1 AND the other number has a 0 (everything else is 0).
For example:
3 => 00011
^ 5 => 00101
------ -------
6 00110
Bitwise NOR (Not OR) means to take the Bitwise OR of two numbers, and then reverse everything (where there was a 0, there's now a 1, where there was a 1, there's now a 0).
Bitwise NAND (Not AND) means to take the Bitwise AND of two numbers, and then reverse everything (where there was a 0, there's now a 1, where there was a 1, there's now a 0).
Continuing: why does word &= 15 set all but the 4 rightmost bits to 0? You should be able to figure it out now...
n => abcdefghjikl
& 15 => 000000001111
------ --------------
? 00000000jikl
(0 AND a = 0, 0 AND b = 0, ... j AND 1 = j, i AND 1 = i, ...)
How is this useful? In many languages, we use things called "bitmasks". A bitmask is essentially a number that represents a whole bunch of smaller numbers combined together. We can combine numbers together using OR, and pull them apart using AND. For example:
int MagicMap = 1;
int MagicWand = 2;
int MagicHat = 4;
If I only have the map and the hat, I can express that as myInventoryBitmask = (MagicMap | MagicHat) and the result is my bitmask. If I don't have anything, then my bitmask is 0. If I want to see if I have my wand, then I can do:
int hasWand = (myInventoryBitmask & MagicWand);
if (hasWand > 0) {
printf("I have a wand\n");
} else {
printf("I don't have a wand\n");
}
Get it?
EDIT: more stuff
You'll also come across the "bitshift" operator: << and >>. This just means "shift everything left n bits" or "shift everything right n bits".
In other words:
1 << 3 = 0001 << 3 = 0001000 = 8
And:
8 >> 2 = 01000 >> 2 = 010 = 2
"Bit" is short for "binary digit". And yes, it's a 0 or 1. There are almost always 8 in a byte, and they're written kinda like decimal numbers are -- with the most significant digit on the left, and the least significant on the right.
In your example, w1 & 3 masks everything but the two least significant (rightmost) digits because 3, in binary, is 00000011. (2 + 1) The AND operation returns 0 if either bit being ANDed is 0, so everything but the last two bits are automatically 0.