C++ Bitwise Operators
Bitwise operators work at the level of individual bits in a number. Each bit in the operands is processed separately, producing new output bits. Bitwise operators are very important in systems programming, binary data manipulation, memory optimization, and embedded systems development.
C++ provides six bitwise operators: AND (&), OR (|), XOR (^), NOT (~), left shift (<<), and right shift (>>). These operators can only be used with integer data types (char, short, int, long).
Bitwise Operator Table
| Operator | Name | Description |
|---|---|---|
& |
Bitwise AND | 1 if both bits are 1 |
\| |
Bitwise OR | 1 if either bit is 1 |
^ |
Bitwise XOR | 1 if the two bits differ |
~ |
Bitwise NOT | Inverts all bits (1's complement) |
<< |
Left Shift | Moves bits to the left |
>> |
Right Shift | Moves bits to the right |
Bitwise Truth Table
| A | B | A & B | A | B | A ^ B |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
Code Example
#include <iostream>
using namespace std;
void printBinary(int n) {
for (int i = 7; i >= 0; i--) {
cout << ((n >> i) & 1);
}
}
int main() {
int a = 12, b = 10;
cout << "=== Bitwise Operators ===" << endl;
cout << "a = " << a << " (bin: ";
printBinary(a);
cout << ")" << endl;
cout << "b = " << b << " (bin: ";
printBinary(b);
cout << ")" << endl;
// Bitwise AND
int andResult = a & b;
cout << "\na & b = " << andResult << " (bin: ";
printBinary(andResult);
cout << ")" << endl;
// Bitwise OR
int orResult = a | b;
cout << "a | b = " << orResult << " (bin: ";
printBinary(orResult);
cout << ")" << endl;
// Bitwise XOR
int xorResult = a ^ b;
cout << "a ^ b = " << xorResult << " (bin: ";
printBinary(xorResult);
cout << ")" << endl;
// Bitwise NOT
int notResult = ~a;
cout << "~a = " << notResult << endl;
// Left Shift
int leftShift = a << 2;
cout << "\na << 2 = " << leftShift << " (x4)" << endl;
cout << "a << 1 = " << (a << 1) << " (x2)" << endl;
// Right Shift
int rightShift = a >> 2;
cout << "a >> 2 = " << rightShift << " (/4)" << endl;
cout << "a >> 1 = " << (a >> 1) << " (/2)" << endl;
// Bit manipulation techniques
cout << "\n=== Bit Manipulation Techniques ===" << endl;
int flags = 0;
// Set bit 0 (value 1)
flags |= (1 << 0);
cout << "Set bit 0 (READ) : " << flags << endl;
// Set bit 1 (value 2)
flags |= (1 << 1);
cout << "Set bit 1 (WRITE) : " << flags << endl;
// Set bit 2 (value 4)
flags |= (1 << 2);
cout << "Set bit 2 (EXECUTE): " << flags << endl;
// Check whether a specific bit is active
bool hasRead = (flags & (1 << 0)) != 0;
bool hasWrite = (flags & (1 << 1)) != 0;
bool hasDelete = (flags & (1 << 3)) != 0;
cout << "\nREAD active? : " << hasRead << endl;
cout << "WRITE active? : " << hasWrite << endl;
cout << "DELETE active? : " << hasDelete << endl;
// Clear bit 1 (remove WRITE)
flags &= ~(1 << 1);
cout << "\nAfter clearing bit 1 (WRITE): " << flags << endl;
// Toggle bit 0
flags ^= (1 << 0);
cout << "After toggling bit 0 (READ): " << flags << endl;
// Swap without a temporary variable
cout << "\n=== Swap Without a Temporary Variable ===" << endl;
int x = 25, y = 37;
cout << "Before: x = " << x << ", y = " << y << endl;
x ^= y;
y ^= x;
x ^= y;
cout << "After: x = " << x << ", y = " << y << endl;
return 0;
}
Code Explanation
- Bitwise AND (
&): Produces 1 only if both bits are 1. Useful for masking (extracting certain bits). - Bitwise OR (
|): Produces 1 if either bit is 1. Useful for setting specific bits. - Bitwise XOR (
^): Produces 1 if the two bits differ. Useful for toggling and swapping. - Bitwise NOT (
~): Inverts all bits. A 1's complement operation. - Left Shift (
<<): Moves all bits to the left. Each shift doubles the value. Example:a << 1is the same asa * 2. - Right Shift (
>>): Moves all bits to the right. Each shift divides the value by 2. Example:a >> 1is the same asa / 2.
Everyday Use Cases
Permission System (Access Rights):
#include <iostream>
#include <string>
using namespace std;
// Definition of permission flags
const int PERM_READ = 1 << 0; // 0001 = 1
const int PERM_WRITE = 1 << 1; // 0010 = 2
const int PERM_EXECUTE = 1 << 2; // 0100 = 4
const int PERM_DELETE = 1 << 3; // 1000 = 8
string permissionToString(int perm) {
string result = "";
if (perm & PERM_READ) result += "R";
if (perm & PERM_WRITE) result += "W";
if (perm & PERM_EXECUTE) result += "X";
if (perm & PERM_DELETE) result += "D";
if (result.empty()) result = "-";
return result;
}
int main() {
// User 1: has all permissions
int user1 = PERM_READ | PERM_WRITE | PERM_EXECUTE | PERM_DELETE;
// User 2: read and execute only
int user2 = PERM_READ | PERM_EXECUTE;
// User 3: no permissions
int user3 = 0;
cout << "=== Permission System ===" << endl;
cout << "User 1: " << permissionToString(user1) << endl;
cout << "User 2: " << permissionToString(user2) << endl;
cout << "User 3: " << permissionToString(user3) << endl;
// Check specific permissions
cout << "\n=== Permission Check ===" << endl;
cout << "Can User 2 write? " << ((user2 & PERM_WRITE) ? "Yes" : "No") << endl;
cout << "Can User 1 delete? " << ((user1 & PERM_DELETE) ? "Yes" : "No") << endl;
// Remove the WRITE permission from User 1
user1 &= ~PERM_WRITE;
cout << "\nUser 1 after removing WRITE: " << permissionToString(user1) << endl;
// Add the WRITE permission to User 2
user2 |= PERM_WRITE;
cout << "User 2 after adding WRITE: " << permissionToString(user2) << endl;
// Even/odd checker without modulus
cout << "\n=== Even/Odd Check ===" << endl;
for (int i = 0; i <= 10; i++) {
string parity = (i & 1) ? "Odd" : "Even";
cout << i << " = " << parity << endl;
}
return 0;
}
Conclusion
Bitwise operators (&, |, ^, ~, <<, >>) work at the level of individual bits. These operators are very efficient and are used extensively in permission systems, flag manipulation, performance optimization, and other binary operations. Common techniques include setting bits with OR, clearing bits with AND NOT, and toggling with XOR. Left shift is equivalent to multiplication and right shift is equivalent to division, making them fast optimization techniques.