Operators

Lesson 58: Using ^ Bitwise XOR Operator

Learn how ^ toggles bits, compares differences, and supports mask-based state flipping in embedded systems.

Progress indicator

Lesson 58 of 58

Learning Objectives

  • Understand what bitwise XOR (^) does at bit level.
  • Read XOR truth-table output and predict bit results quickly.
  • Use XOR masks to toggle selected bits without changing others.
  • Compare XOR with logical operators and avoid mixing intent.
  • Apply XOR in practical embedded state-flip patterns.

Concept Explanation

What is the Bitwise XOR Operator (^)

The ^ operator compares each bit pair and returns 1 only when bits are different.

Same bits produce 0. Different bits produce 1. This makes XOR very useful for toggling.

Bitwise XOR Syntax

result = valueA ^ valueB;
flags = flags ^ MASK;

How ^ Works

  1. Convert both values to binary.
  2. Compare each bit position.
  3. If bits are different, output bit is 1.
  4. If bits are same, output bit is 0.

Example: 0b1010 ^ 0b1100 = 0b0110.

Bitwise Truth Table

ABA ^ B
000
011
101
110

Using ^ with Bit Masks

XOR with a mask flips selected bits:

  • Mask bit = 1: target bit toggles.
  • Mask bit = 0: target bit stays unchanged.
flags = flags ^ 0b00000001; // toggle bit 0
flags = flags ^ 0b00000001; // toggle back

^ vs Logical Operators (Comparison)

OperatorWorks onUse case
^Integer bitsToggle/compare bit differences
&&Boolean conditionsLogical AND in if/else
||Boolean conditionsLogical OR in if/else

When to Use ^

  • Toggling LEDs/features in one instruction.
  • Comparing which bits changed between two values.
  • Implementing compact state flip logic in embedded systems.

Example Code

This sketch toggles LED and logging bits with XOR, then reads current bit states.

const int LED_PIN = 2;

byte flags = 0b00000000;
const byte LED_TOGGLE_MASK = 0b00000001;
const byte LOG_TOGGLE_MASK = 0b00000100;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  flags = flags ^ LED_TOGGLE_MASK;
  flags = flags ^ LOG_TOGGLE_MASK;

  byte ledBit = flags & LED_TOGGLE_MASK;
  byte logBit = flags & LOG_TOGGLE_MASK;

  if (ledBit) {
    digitalWrite(LED_PIN, HIGH);
  } else {
    digitalWrite(LED_PIN, LOW);
  }

  if (logBit) {
    Serial.print("flags=");
    Serial.print(flags, BIN);
    Serial.print(", ledBit=");
    Serial.print(ledBit ? 1 : 0);
    Serial.print(", logBit=");
    Serial.println(logBit ? 1 : 0);
  }

  delay(600);
}

Example Code Explanation

  1. flags starts with all bits 0.
  2. flags ^ LED_TOGGLE_MASK flips bit 0 every loop.
  3. flags ^ LOG_TOGGLE_MASK flips bit 2 every loop.
  4. ledBit and logBit read current bit states with AND masks.
  5. LED output uses the current value of ledBit.
  6. Serial prints debug details only when logBit is active.

What Happens Inside

  1. CPU loads current flags and XOR mask.
  2. ALU compares each bit pair with XOR rule.
  3. Selected bits are toggled in result.
  4. Updated flags are written back to memory.
  5. Bit masks read back toggled bits for control flow.
OperationBeforeAfterMeaning
flags ^ 000000010000000000000001LED bit toggled ON
flags ^ 000001000000000100000101Log bit toggled ON
same mask again0000010100000000Both bits toggled back OFF

Common Mistakes with ^

  • Thinking ^ means exponent (power).
  • Toggling wrong bit due to incorrect mask value.
  • Using XOR in boolean if-conditions when logical operators were intended.
  • Forgetting that applying same XOR mask twice restores original bits.

Best Practices for ^

  • Use clear mask names like LED_TOGGLE_MASK.
  • Keep XOR expressions simple and isolate bit checks in separate variables.
  • Print binary values to verify which bits toggled.
  • Document which bit each mask controls in comments/lesson notes.

Try it now

Open the simulator workspace and observe XOR bit toggling in each loop cycle.

Run in Simulator