In nearly all programming languages bitwise operations rely on 6 operators, these are
- And – &
- Or – |
- XOR – ^
- Not – ~
- Shift Left – <<
- Shift Right – >>
Its easier to understand these operations through examples

The result of an AND operation is the resulting bits are set to 1 when both bits in each value are 1 and set to 0 for any other combination

The result of an OR operation is that each bit in the result is set to 1 if either of the corresponding bits in either value is 1, otherwise, they are set to 0

For XOR operations, the result is 1 only if one of the 2 corresponding values is 1, otherwise the resulting bit is 0

NOT swaps the bit values setting the resulting bit to 1 when the value bit is 0, and 0 when the value bit is 1. This in effect is a negation

Shift Left moves all bits in the value 1 or more positions to the left. It most cases in assembly language you can control if the bits moved out of the left-most bit wrap-around, or are replaced with a 0. Shift left is the equivalent of multiplying the value by 2.

Shift Right moves all bits in the value 1 or more positions to the right. It most cases in assembly language you can control if the bits moved out of the right-most bit wrap-around, or are replaced with a 0. Shift Right is the equivalent of dividing the value by 2
Useful Bitwise Operations
If these examples we will use Python to carry out the operation and print the result out in the numeric and binary format. For this, we are going to use the following function
1 2 3 | def bindigits(n, bits): s = bin(n & int("1"*bits, 2))[2:] return ("{0:0>%s}" % (bits)).format(s) |
Which when executed prints the following
1 2 | >>> bindigits (32, 8) 00100000 |
Check if a number is Odd/Even: n & 1
This is one of the simplest operations and probably the easiest to understand. Any odd number if binary will have the first bit set, so all we need to do is AND the value we are checking with 1. The result is either 1 for odd or 0 for even
1 2 3 4 | >>> (31 & 1) // 31 = 00011111 1 >>> (32 & 1) // 32 = 00100000 0 |
Multiple by nth power of 2: x << n
1 2 3 4 5 6 | >>> 1 << 1 // 00000001 => 00000010 2 >>> 2 << 1 // 00000010 => 00000100 4 >>> 2 << 2 // 00000100 => 00001000 8 |
Divide by the nth power of 2: x >> n
1 2 3 4 5 6 7 8 | >>> 1 >> 1 // 00000001 => 00000000 0 >>> 2 >> 1 // 00000010 => 00000001 1 >>> 4 >> 1 // 00000100 => 00000010 2 >>> 8 >> 1 // 00001000 => 00000100 4 |
Set the nth bit of an integer : x | ( 1 << n )
To set the nth bit of an integer we OR the original value with the value of 1 shift 1 position. Note we are using 0-based indexing, so the first bit is 0, the second bit is 1 etc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | binary(4) 4 = 00000100 >>> binary(4 | 1 << 1) // Set the 2nd bit 6 = 00000110 >>> binary(20 | 1 << 1) // Set the 2nd bit 22 = 00010110 >>> binary(20 | 1 << 0) // Set the 1st bit 21 = 00010101 >>> binary(20) 20 = 000010100 binary(20 | 1 << 8) // Set the nth bit 276 = 100010100 |
Unset the nth bit of an integer: x & ~(1 << n)
1 2 3 4 5 6 7 8 9 10 11 | >>> binary (23) 23 = 00010111 >>> binary (23 & ~(1<<2)) // Unset the 3rd bit 19 = 00010011 // Break it down (1<<2) = 00000100 ~(1<<2) = 11111011 23 = 00010111 & -------- 00010011 = 19 |
Check the equality of 2 integers: x ^ y
To check the equality of two integers we can use the ZOR operation. This takes 2 values and sets the corresponding bit in the result value to 1 if the values in the two integers are not the same, and 0 if they are the same, so 1 ^ 1 = 0, 1 ^ 0 = 1, 0 ^ 1 = 1 and 0 ^ 0 = 0
1 2 3 4 5 6 7 8 9 | 23 = 00010111 23 = 00010111 ^ -------- 00000000 23 = 00010111 24 = 00011000 ^ -------- 00001111 = 15 |
Swap 2 integer values: a ^= b, b ^= a, a ^= b
1 2 3 4 5 6 | a = 23 = 00010111 b = 27 = 00011011 a ^= b = 00001100 == 12 b ^= a = 00010111 == 23 a ^= b = 00011011 == 27 |
Check if 2 integers have the same sign: (num1 ^ num2) >= 0
Flip the sign of an integer: ~num + 1
1 2 3 | 234 = 11101010 ~234 = 00010101 +1 = 00010110 // Twos complement of -234 |
Increment an integer by 1: -~num
This example shows how negative numbers are represented in binary. The negation operator returns a binary value where all the bits in the value have been flipped, 1’s for 0’s and 0’s for 1. This results in the negation returning for positive numbers a number that is numerically 1 greater than our number but with the sign flipper, and for negative numbers, a number that is numerically one less than our number but with a +sign
1 2 3 | 234 = 11101010 ~234 = 00010110 // Twos complement -(-235) = 11100101 // == 235 |
Decrement an integer by 1: ~-num
This example shows how negative numbers are represented in binary. The negation operator returns a binary value where all the bits in the value have been flipped, 1’s for 0’s and 0’s for 1. This results in the negation returning for positive numbers a number that is numerically 1 greater than our number but with the sign flipper, and for negative numbers, a number that is numerically one less than our number but with a +sign
1 2 3 | 234 = 11101010 -234 = 00010110 // Twos complement ~(-234) = 11101011 // == 233 |