Bitwise means operators operate bit-by-bit on the binary representation of their operands. Bitwise operators are very useful in programming. It allows the programmer to write efficient code to perform certain operations fast, i.e. these operators have the ability to speed up certain operations.
Bitwise Operators only work with int and char data type. There is two categories of Bitwise operators; Bitwise (AND, OR, XOR, NOT) and Bitshift (<<, >>):
Bitwise Operators only work with int and char data type. There is two categories of Bitwise operators; Bitwise (AND, OR, XOR, NOT) and Bitshift (<<, >>):
Operator
|
Meaning
|
---|---|
&
|
Bitwise AND
|
|
|
Bitwise OR
|
^
|
Bitwise Exclusive OR
|
~
|
One's Complement(NOT)
|
<<
|
Left Shift
|
>>
|
Right Shi
|
(A) Bitwise Operators (&, |, ^ and ~):
There are two types of Bitwise operators; unary(~) operators and binary (&, |, ^) operators. Bitwise operators works like logical operators; except that these operators work with bits instead of expression.
Here, AND (&) returns 1 if and only if both of its operands are equal to 1, returns 0 otherwise; OR (|) returns 0 if and only if both of its operands are 0, return 1 otherwise; XOR (^) returns 1 if and only if exactly one of its operands is 1. If both operands are 0 or 1, then returns 0. Finally, unary NOT (~) operator inverts all the bits in its operand, i.e. 0 changes to 1 and vice versa. See the following table:
x
|
y
|
x & y
|
x
| y
|
x
^ y
|
~x
|
0
|
0
|
0
|
0
|
0
|
1
|
0
|
1
|
0
|
1
|
1
|
1
|
1
|
0
|
0
|
1
|
1
|
0
|
1
|
1
|
1
|
1
|
0
|
0
|
Example 1: suppose x = 10, y = 13. So the binary representation of x and y is:
x = 0 0 0 0 1 0 1 0
y = 0 0 0 0 1 1 0 1
------------------------------
0 0 0 0 1 0 0 0 = 8 (AND)
0 0 0 0 1 1 1 1 = 15(OR)
0 0 0 0 0 1 1 1 = 7(XOR)
~x = 1 1 1 1 0 1 0 1 = -11(Ones's Complement(NOT))
~x + 1 = 1 1 1 1 0 1 1 0 = -10(Two's Complement)
You may run the following code:
int main()
{
int x = 10, y = 13;
printf("%d\n", x & y);
printf("%d\n", x | y);
printf("%d\n", x ^ y);
printf("%d\n", ~x);
printf("%d", ~x+1);
return 0;
}
(B) Bitshift(<<, >>) Operators:
There are two Bitwise shift operators; left shift (<<) and right shift (>>). Here, the shift means to shift the bits to left or right. The Bitshift operators take two arguments like below:
x << n or x >> n
Where, x can be any int/char variables and n should be int variable.
(1) Left Shift (<<): The left shift operator (x << n) shifts the bits of x to the left by n-bits. For example, x = 10 and n = 2.
Then...
x = 0 0 0 0 1 0 1 0 << 2 = 0 0 1 0 1 0 0 0 = 40 (10✕4)
i.e. left shifts by n-bits equivalent to multiplying by 2n. Again suppose, if we want to multiply 7 by 8, then we need to
shift 7 left by 3 bits(23).
0 0 0 0 0 1 1 1 < 3 = 0 0 1 1 1 0 0 0 = 56 (7✕8)
(2) Right Shift (>>): The right shift operator (x >> n) shifts the bits of x to the right by n-bits. For example, x = 10 and n = 1.
Then...
x = 0 0 0 0 1 0 1 0 >> 1 = 0 0 0 0 0 1 0 1 = 5 (10/2)
i.e. right shifts by n-bits equivalent to dividing by 2n. Again suppose, we want to divide 32 by 8, then we need to
shift 32 right by 3 bits(23).
0 0 1 0 0 0 0 0 >> 3 = 0 0 0 0 0 1 0 0 = 4 (32/8)
x << n or x >> n
Where, x can be any int/char variables and n should be int variable.
(1) Left Shift (<<): The left shift operator (x << n) shifts the bits of x to the left by n-bits. For example, x = 10 and n = 2.
Then...
x = 0 0 0 0 1 0 1 0 << 2 = 0 0 1 0 1 0 0 0 = 40 (10✕4)
i.e. left shifts by n-bits equivalent to multiplying by 2n. Again suppose, if we want to multiply 7 by 8, then we need to
shift 7 left by 3 bits(23).
0 0 0 0 0 1 1 1 < 3 = 0 0 1 1 1 0 0 0 = 56 (7✕8)
(2) Right Shift (>>): The right shift operator (x >> n) shifts the bits of x to the right by n-bits. For example, x = 10 and n = 1.
Then...
x = 0 0 0 0 1 0 1 0 >> 1 = 0 0 0 0 0 1 0 1 = 5 (10/2)
i.e. right shifts by n-bits equivalent to dividing by 2n. Again suppose, we want to divide 32 by 8, then we need to
shift 32 right by 3 bits(23).
0 0 1 0 0 0 0 0 >> 3 = 0 0 0 0 0 1 0 0 = 4 (32/8)
(C) Some Useful Applications of Bitwise Operators: Fast Bitwise Operations
(1) Fast modulus (%) operation using Bitwise AND (&): If the divisor of modulus operation is power of 2,
then you can do the modulus operation following way:
modulus = numerator & (divisor - 1 ) e.g. modulus = 29 & (4-1) = 29 & 3 = 1
Again suppose, we want to find the modulus of 35 and 8 i.e. (35%8 = 3) then modulus = 35 & (8-1) = 35 & 7 = 3
(2) To check whether an integer number is EVEN or ODD using Bitwise AND (&):
if((number % 2) == 0) if((number & 1) == 0)
EVEN Number Equivalent to EVEN Number
else else
ODD Number ODD Number
(3) Swapping integer numbers without a temporary variable using Bitwise XOR (^):
temp = a a ^= b
a = b Equivalent to b ^= a
b = a a ^= b
You may run the following code:
int main()
{
int a = 10, b = 15;
printf("Before Swap: a = %d and b = %d", a ,b);
a ^= b;
b ^= a;
a ^= b;
printf("\nAfter Swap: a = %d and b = %d", a ,b);
return 0;
}
(4) Use of Bit Masking:
A mask is a bit string in which purpose is either to access an individual bit (or range of bits) or to modify individual bit
(or range of bits) i.e. mask bits defines which bits we want to use, which bits we want to set or which bits we want
to clear.
(i) Extract subset of the bits in the value using Bitwise AND (&): Suppose we want to use lower 4-bits of a bit string
and other higher bits set to zero. Then, we know that ANDing with the 1 bit will keep the bits we wanted and ANDing
with 0 bit will turn all the others bits to zeros.
mask = 0 0 0 0 1 1 1 1 = 0Fh
value = 1 0 0 1 0 1 0 1 = 95h
------------------------------------
AND = 0 0 0 0 0 1 0 1 = 05h
i.e. ANDing clear the higher 4-bits and keep the lower 4-bits.
(ii) To check whether a specific bit is set or not using Bitwise AND(&)? Suppose, we want to check the ith bit of
a value set or not. Then mask:
mask = 1 << (i-1) {if i = 4 then 1 << (4-1) = 0 0 0 0 1 0 0 0 = 08h}
mask = 0 0 0 0 1 0 0 0 = 08h
value = 1 0 1 0 1 1 0 1 = ADh
-----------------------------------------
AND = 0 0 0 0 1 0 0 0 = 08h
if((mask & value) != 0) then bit is set else bit not set. You may run the following code:
int main()
{
int value = 173;
int mask = 1 << (4-1);
if((mask & value) != 0)
printf("Bit Set");
else
printf("Bit not Set");
return 0;
}
(iii) To set a specific bit using Bitwise OR(|): Suppose, we want to set the ith bit of a value, then mask:
mask = 1 << (i-1) {if i = 4 then 1 << (4-1) = 0 0 0 0 1 0 0 0 = 08h}
mask = 0 0 0 0 1 0 0 0 = 08h
value = 1 0 1 0 0 1 0 1 = A5h
-----------------------------------------
OR = 1 0 1 0 1 1 0 1 = ADh
so (mask | value) set the 4th bit of value to 1. You may run the following code:
int main()
{
int value = 165; //165=10100101
int mask = 1 << (4-1);//8=00001000
value |= mask;//10101101=173
printf("%d", value);
return 0;
}
(iv) To clear a specific bit using Bitwise XOR(^): XORing toggle the subset of the bits. Suppose you want to clear
the ith bit of a value, then mask:
mask = 1 << (i-1) {if i = 4 then 1 << (4-1) = 0 0 0 0 1 0 0 0 = 08h}
mask = 0 0 0 0 1 0 0 0 = 08h
value = 1 0 1 0 1 1 0 1 = ADh
-----------------------------------------
XOR = 1 0 1 0 0 1 0 1 = A5h
so (mask ^ value) clear the 4th bit of value to 0. You may run the following code:
int main()
{
int value = 173; //173=10101101
int mask = 1 << (4-1);//00001000=8
value ^= mask;//10100101=165
printf("%d", value);
return 0;
}
(v) ASCII character to Lower-Case using OR(|) and to Upper-Case using AND(&): The difference between ASCII
lower-case and upper-case is 0 0 1 0 0 0 0 0 (32d or 20h). Any ASCII character ORing with 20h becomes lower-case.
if the character already in lower-case then it makes no difference.
E.g. ASCII character 'A' equivalent to 65d or 41h (0 0 1 0 0 0 0 1)
'A' = 0 1 0 0 0 0 0 1 = 41h
mask = 0 0 1 0 0 0 0 0 = 20h
--------------------------------------
OR = 0 1 1 0 0 0 0 1 = 61h equivalent to lower-case 'a'
You may run the following code:
int main()
{
char ch;
for(ch = 'A'; ch <= 'Z'; ch = ch + 1)
printf("%c, ", ch | 32);
return 0;
}
Any ASCII character ANDing with DFh or 223d(1101 1111) becomes upper-case. if the character already in upper-case
then it makes no difference.
E.g. ASCII character 'a' equivalent to 97d or 61h (0 1 1 0 0 0 0 1)
'a' = 0 1 1 0 0 0 0 1 = 61h
mask = 1 1 0 1 1 1 1 1 = DFh
--------------------------------------
AND = 0 1 0 0 0 0 0 1 = 41h equivalent to Upper-case 'A'
You may run the following code:
int main()
{
char ch;
for(ch = 'a'; ch <= 'z'; ch = ch + 1)
printf("%c, ", ch & 223);
return 0;
}
then you can do the modulus operation following way:
modulus = numerator & (divisor - 1 ) e.g. modulus = 29 & (4-1) = 29 & 3 = 1
Again suppose, we want to find the modulus of 35 and 8 i.e. (35%8 = 3) then modulus = 35 & (8-1) = 35 & 7 = 3
(2) To check whether an integer number is EVEN or ODD using Bitwise AND (&):
if((number % 2) == 0) if((number & 1) == 0)
EVEN Number Equivalent to EVEN Number
else else
ODD Number ODD Number
(3) Swapping integer numbers without a temporary variable using Bitwise XOR (^):
temp = a a ^= b
a = b Equivalent to b ^= a
b = a a ^= b
You may run the following code:
int main()
{
int a = 10, b = 15;
printf("Before Swap: a = %d and b = %d", a ,b);
a ^= b;
b ^= a;
a ^= b;
printf("\nAfter Swap: a = %d and b = %d", a ,b);
return 0;
}
A mask is a bit string in which purpose is either to access an individual bit (or range of bits) or to modify individual bit
(or range of bits) i.e. mask bits defines which bits we want to use, which bits we want to set or which bits we want
to clear.
(i) Extract subset of the bits in the value using Bitwise AND (&): Suppose we want to use lower 4-bits of a bit string
and other higher bits set to zero. Then, we know that ANDing with the 1 bit will keep the bits we wanted and ANDing
with 0 bit will turn all the others bits to zeros.
mask = 0 0 0 0 1 1 1 1 = 0Fh
value = 1 0 0 1 0 1 0 1 = 95h
------------------------------------
AND = 0 0 0 0 0 1 0 1 = 05h
i.e. ANDing clear the higher 4-bits and keep the lower 4-bits.
(ii) To check whether a specific bit is set or not using Bitwise AND(&)? Suppose, we want to check the ith bit of
a value set or not. Then mask:
mask = 1 << (i-1) {if i = 4 then 1 << (4-1) = 0 0 0 0 1 0 0 0 = 08h}
mask = 0 0 0 0 1 0 0 0 = 08h
value = 1 0 1 0 1 1 0 1 = ADh
-----------------------------------------
AND = 0 0 0 0 1 0 0 0 = 08h
if((mask & value) != 0) then bit is set else bit not set. You may run the following code:
int main()
{
int value = 173;
int mask = 1 << (4-1);
if((mask & value) != 0)
printf("Bit Set");
else
printf("Bit not Set");
return 0;
}
(iii) To set a specific bit using Bitwise OR(|): Suppose, we want to set the ith bit of a value, then mask:
mask = 1 << (i-1) {if i = 4 then 1 << (4-1) = 0 0 0 0 1 0 0 0 = 08h}
mask = 0 0 0 0 1 0 0 0 = 08h
value = 1 0 1 0 0 1 0 1 = A5h
-----------------------------------------
OR = 1 0 1 0 1 1 0 1 = ADh
so (mask | value) set the 4th bit of value to 1. You may run the following code:
int main()
{
int value = 165; //165=10100101
int mask = 1 << (4-1);//8=00001000
value |= mask;//10101101=173
printf("%d", value);
return 0;
}
(iv) To clear a specific bit using Bitwise XOR(^): XORing toggle the subset of the bits. Suppose you want to clear
the ith bit of a value, then mask:
mask = 1 << (i-1) {if i = 4 then 1 << (4-1) = 0 0 0 0 1 0 0 0 = 08h}
mask = 0 0 0 0 1 0 0 0 = 08h
value = 1 0 1 0 1 1 0 1 = ADh
-----------------------------------------
XOR = 1 0 1 0 0 1 0 1 = A5h
so (mask ^ value) clear the 4th bit of value to 0. You may run the following code:
int main()
{
int value = 173; //173=10101101
int mask = 1 << (4-1);//00001000=8
value ^= mask;//10100101=165
printf("%d", value);
return 0;
}
(v) ASCII character to Lower-Case using OR(|) and to Upper-Case using AND(&): The difference between ASCII
lower-case and upper-case is 0 0 1 0 0 0 0 0 (32d or 20h). Any ASCII character ORing with 20h becomes lower-case.
if the character already in lower-case then it makes no difference.
E.g. ASCII character 'A' equivalent to 65d or 41h (0 0 1 0 0 0 0 1)
'A' = 0 1 0 0 0 0 0 1 = 41h
mask = 0 0 1 0 0 0 0 0 = 20h
--------------------------------------
OR = 0 1 1 0 0 0 0 1 = 61h equivalent to lower-case 'a'
You may run the following code:
int main()
{
char ch;
for(ch = 'A'; ch <= 'Z'; ch = ch + 1)
printf("%c, ", ch | 32);
return 0;
}
Any ASCII character ANDing with DFh or 223d(1101 1111) becomes upper-case. if the character already in upper-case
then it makes no difference.
E.g. ASCII character 'a' equivalent to 97d or 61h (0 1 1 0 0 0 0 1)
'a' = 0 1 1 0 0 0 0 1 = 61h
mask = 1 1 0 1 1 1 1 1 = DFh
--------------------------------------
AND = 0 1 0 0 0 0 0 1 = 41h equivalent to Upper-case 'A'
You may run the following code:
int main()
{
char ch;
for(ch = 'a'; ch <= 'z'; ch = ch + 1)
printf("%c, ", ch & 223);
return 0;
}