What are the bitwise AND, OR, XOR, NOT, and shift operators in C?
C provides six bitwise operators that work on individual bits of integer values:
| Operator | Symbol | Description |
|---|---|---|
| AND | & |
1 only if both bits are 1 |
| OR | \| |
1 if either bit is 1 |
| XOR | ^ |
1 if bits are different |
| NOT | ~ |
Flips all bits (one's complement) |
| Left shift | << |
Shifts bits left, fills with 0 |
| Right shift | >> |
Shifts bits right (arithmetic or logical) |
Key properties:
- AND: masking (extract bits), clearing bits
- OR: setting bits
- XOR: toggling bits, finding differences, self-inverse (a ^ a = 0)
- NOT: one's complement, ~x = -(x+1) for signed integers
- Left shift by n: multiplies by 2^n
- Right shift by n: divides by 2^n (for unsigned; implementation-defined for signed)
AND: 1010 & 1100 = 1000 (bits set in BOTH)
OR: 1010 | 1100 = 1110 (bits set in EITHER)
XOR: 1010 ^ 1100 = 0110 (bits that DIFFER)
NOT: ~1010 = 0101 (flip all bits)
<<: 0011 << 2 = 1100 (multiply by 4)
>>: 1100 >> 2 = 0011 (divide by 4)
#include <stdio.h>
int main(void) {
unsigned int a = 0b1010; /* 10 in decimal */
unsigned int b = 0b1100; /* 12 in decimal */
printf("a & b = %u\n", a & b); /* 8 (1000) */
printf("a | b = %u\n", a | b); /* 14 (1110) */
printf("a ^ b = %u\n", a ^ b); /* 6 (0110) */
printf("~a = %u\n", ~a); /* 4294967285 (all bits flipped) */
printf("a << 2 = %u\n", a << 2); /* 40 (101000) -- multiply by 4 */
printf("b >> 2 = %u\n", b >> 2); /* 3 (0011) -- divide by 4 */
/* XOR properties */
printf("\nXOR properties:\n");
printf("a ^ 0 = %u\n", a ^ 0); /* a (identity) */
printf("a ^ a = %u\n", a ^ a); /* 0 (self-inverse) */
printf("a ^ b ^ b = %u\n", a ^ b ^ b); /* a (cancellation) */
/* NOT on signed integer */
int x = 5;
printf("\n~5 = %d\n", ~x); /* -6 (two's complement: ~x = -(x+1)) */
/* Left shift = multiply by power of 2 */
printf("3 << 4 = %d\n", 3 << 4); /* 48 = 3 * 16 */
/* Right shift = divide by power of 2 */
printf("48 >> 3 = %d\n", 48 >> 3); /* 6 = 48 / 8 */
return 0;
}
- •& (AND): both bits 1 -> 1. Used for masking and clearing bits
- •| (OR): either bit 1 -> 1. Used for setting bits
- •^ (XOR): different bits -> 1. Self-inverse: a ^ a = 0
- •<< n: multiply by 2^n. >> n: divide by 2^n (unsigned)
- •~ (NOT): flips all bits. ~x = -(x+1) for signed (two's complement)
- •Do not confuse & (bitwise AND) with && (logical AND)
- •Do not confuse | (bitwise OR) with || (logical OR)
- •Right shift of signed negative integers is implementation-defined (arithmetic vs logical)
- •Shifting by a negative amount or by >= bit width is undefined behavior
- •Operator precedence: bitwise operators bind weaker than comparison -- use parentheses: (a & b) == 0, not a & b == 0