New:Embedded & IoT Bootcamp
Tutorial 6 of 7 in series

Bitwise Operators

Bitwise operators in Arduino.

Abhishek Sharma 2026-05-30 Embedded/IoT / Arduino / Programming / Control & Operators
86%

Bitwise Operators

Bitwise operators perform operations on individual bits of integer values. Unlike Boolean operators (&&, ||, !) which work on logical true/false values, bitwise operators work directly on the binary representation of numbers. They are essential for setting, clearing, and testing individual bits in registers, flags, and hardware control bytes.

& (bitwise AND)

The & operator compares each bit of two values. A result bit is 1 only if both corresponding bits are 1. It is commonly used to mask (clear) specific bits.

void setup() {
  Serial.begin(9600);
  byte a = 0b11001100;
  byte b = 0b11110000;
  byte result = a & b;
  Serial.println(result, BIN);  // prints 11000000
}

void loop() {
  // nothing to do here
}

In this example, only bits that are 1 in both a and b remain 1. The lower 4 bits of a are cleared because b has 0s there. Use & with a mask to clear specific bits while preserving others.

| (bitwise OR)

The | operator compares each bit of two values. A result bit is 1 if either corresponding bit is 1. It is commonly used to set specific bits.

void setup() {
  Serial.begin(9600);
  byte a = 0b00001111;
  byte b = 0b11110000;
  byte result = a | b;
  Serial.println(result, BIN);  // prints 11111111
}

void loop() {
  // nothing to do here
}

Here, a | b combines the bits - all 8 bits are set because each position has a 1 in at least one operand. Use | with a mask to set specific bits to 1 without altering other bits.

^ (bitwise XOR)

The ^ operator compares each bit of two values. A result bit is 1 if the corresponding bits are different. XOR is useful for toggling bits - applying the same mask twice restores the original value.

void setup() {
  Serial.begin(9600);
  byte a = 0b11110000;
  byte toggle = 0b11111111;
  byte result = a ^ toggle;
  Serial.println(result, BIN);  // prints 1111 (00001111)

  // XOR twice restores the original
  byte restored = result ^ toggle;
  Serial.println(restored, BIN);  // prints 11110000
}

void loop() {
  // nothing to do here
}

In this example, XOR with 0b11111111 flips all bits, inverting the value. XORing again with the same mask restores the original. This makes ^ ideal for toggling LED states or flipping control bits.

~ (bitwise NOT)

The ~ operator inverts all bits of a value - 1s become 0s and 0s become 1s. It is a unary operator that acts on a single operand.

void setup() {
  Serial.begin(9600);
  byte a = 0b11110000;
  byte result = ~a;
  Serial.println(result, BIN);  // prints 11111111111111111111111100001111
}

void loop() {
  // nothing to do here
}

Note that ~a prints many leading 1s because byte is promoted to int before the NOT operation, and the higher bits of the int are inverted as well. To mask back to a single byte, combine with &: byte result = ~a & 0xFF;. The NOT operator is often used to create masks for clearing bits: flags &= ~(1 << 3); clears bit 3.

<< (left shift)

The << operator shifts all bits of a value to the left by a specified number of positions. Bits shifted off the left end are lost, and zeros fill in on the right. Each left shift multiplies the value by 2.

void setup() {
  Serial.begin(9600);
  byte x = 1;
  for (int i = 0; i < 8; i++) {
    Serial.println(x << i, BIN);  // prints 1, 10, 100, 1000, ...
  }

  // Calculate 2^5 using left shift
  int power = 1 << 5;  // 32
  Serial.println(power);  // prints 32
}

void loop() {
  // nothing to do here
}

This example shows how shifting 1 left by i positions produces powers of two. Left shift is faster than multiplication and is the standard way to create bit masks: 1 << 3 gives 0b00001000, which is useful for targeting bit 3.

>> (right shift)

The >> operator shifts all bits of a value to the right by a specified number of positions. Bits shifted off the right end are lost. For unsigned types, zeros fill in on the left. Each right shift divides the value by 2 (truncating).

void setup() {
  Serial.begin(9600);
  byte x = 0b11110000;
  byte result = x >> 4;
  Serial.println(result, BIN);  // prints 1111

  int value = 256;
  for (int i = 0; i < 4; i++) {
    value >>= 1;  // divide by 2 each time
    Serial.println(value);  // prints 128, 64, 32, 16
  }
}

void loop() {
  // nothing to do here
}

This example shifts the upper nibble of x down to the lower nibble, effectively isolating it. Right shift is faster than division and is commonly used to extract specific bit fields from sensor data or register values.

Keep learning

Related tutorials from across the library.

All tutorials
Tutorial2026-05-30

Control Structure

Control flow structures in Arduino.

Embedded/IoT / Arduino / Programming / Control & Operators

Arduino
Tutorial2026-05-30

Arithmetic Operators

Arithmetic operators in Arduino.

Embedded/IoT / Arduino / Programming / Control & Operators

Arduino
Tutorial2026-05-30

Comparison Operators

Comparison operators in Arduino.

Embedded/IoT / Arduino / Programming / Control & Operators

Arduino