Bitwise Operators in C Programming
The C programming language provides direct, low-level access to
memory through six native bitwise operators that manipulate integral
data types at the individual bit level. These operators allow developers
to perform fundamental logic and shift operations directly on the binary
representation of integers (char, short,
int, long, signed or unsigned). This article
covers each of the six native bit manipulation operators in C,
explaining their syntax, mechanics, and common applications in embedded
systems, optimization, and low-level software design.
Bitwise AND (&)
The bitwise AND operator compares corresponding bits of two integer
operands. For each bit position, the resulting bit evaluates to
1 if and only if both input bits are 1;
otherwise, it evaluates to 0.
- Syntax:
result = a & b; - Common Use Case (Masking): It is frequently used to
clear specific bits or check the status of an individual bit (flag). For
example,
flags & 0x01checks if the least significant bit is set.
Bitwise OR (|)
The bitwise OR operator compares corresponding bits of two operands.
The resulting bit is 1 if at least one of the corresponding
bits is 1. It only yields 0 if both bits are
0.
- Syntax:
result = a | b; - Common Use Case (Setting Bits): It is commonly used
to turn on (set to
1) specific bits without altering other bits in the register. For example,flags | 0x02sets the second bit to1.
Bitwise XOR (^)
The bitwise XOR (exclusive OR) operator compares corresponding bits
of two operands. The resulting bit is 1 if the input bits
are different (one is 0 and the other is 1).
If both bits are the same (0 and 0, or
1 and 1), the result is 0.
- Syntax:
result = a ^ b; - Common Use Case (Toggling Bits): XOR is standard
for inverting or toggling specific bits. For example,
flags ^ 0x04inverts the state of the third bit. It is also used in simple cryptography and parity calculations.
Bitwise NOT / One's Complement
(~)
The bitwise NOT operator is a unary operator that inverts all the
bits of its single operand. Every 0 bit becomes
1, and every 1 bit becomes 0.
- Syntax:
result = ~a; - Common Use Case (Mask Generation): It is often
paired with the AND operator to clear bits cleanly. For instance,
flags &= ~0x01clears the lowest bit while leaving all other bits intact, regardless of the integer's total width.
Left Shift (<<)
The left shift operator shifts the bits of the left-hand operand to the left by the number of positions specified by the right-hand operand. Vacated bits on the right are filled with zeros, while bits shifted off the high-order end are discarded.
- Syntax:
result = a << n; - Common Use Case (Multiplication by Powers of Two): Shifting an unsigned integer to the left by \(n\) positions is mathematically equivalent to multiplying that integer by \(2^n\), provided no overflow occurs.
Right Shift (>>)
The right shift operator moves the bits of the left-hand operand to the right by the number of positions specified by the right-hand operand. Bits shifted off the low-order end are discarded.
- Syntax:
result = a >> n; - Behavior on Leading Bits: For unsigned types, vacated positions on the left are always filled with zeros (logical shift). For signed types, the behavior depends on the implementation, but most systems perform an arithmetic shift, preserving the sign bit by filling vacated positions with copies of the original sign bit.
- Common Use Case (Division by Powers of Two): Shifting an unsigned integer to the right by \(n\) positions performs an integer division by \(2^n\).
Compound Bitwise Assignment Operators
C also natively provides shorthand compound assignment operators for each of the binary bitwise operations:
&=(Bitwise AND assignment)|=(Bitwise OR assignment)^=(Bitwise XOR assignment)<<=(Left shift assignment)>>=(Right shift assignment)
These operators allow in-place modification of variables (for
example, reg |= 0x10; directly sets bit 4 on
reg).