Skip to content

Expert · Bits, undefined behaviour and safety · topic 41 of 60 · 30 min

Bitwise operators

Explanation

Bitwise operators work on the individual bits of integers: & (AND), | (OR), ^ (XOR), ~ (NOT), << (shift left) and >> (shift right). Shifting left by n multiplies by 2^n and shifting right divides (for unsigned values). Use unsigned types for bit work: shifting negative numbers or shifting by the type's width or more is implementation-defined or undefined.

Binary and hexadecimal

Computers store integers in binary: 13 is 1101 (8 + 4 + 0 + 1). Hexadecimal groups 4 bits into one digit (0–9, A–F), so a byte is two hex digits: 0xFF is 11111111 (255), 0x0F is 00001111. Hex is the usual way to write bit patterns in C; C23 also allows binary literals like 0b1101 (and GCC has long supported them as an extension).

output
decimal   binary (8 bits)   hex
   13     0000 1101         0x0D
  200     1100 1000         0xC8
  255     1111 1111         0xFF

The operators

output
unsigned a = 0xC8;   /* 1100 1000 */
unsigned b = 0x0D;   /* 0000 1101 */

a & b   →  0000 1000  = 0x08   AND: 1 only where BOTH are 1
a | b   →  1100 1101  = 0xCD   OR: 1 where EITHER is 1
a ^ b   →  1100 0101  = 0xC5   XOR: 1 where they DIFFER
~b      →  1111 … 1111 0010     NOT: flips every bit (all 32 bits of an unsigned int)
b << 2  →  0011 0100  = 0x34   shift left 2: × 4
a >> 3  →  0001 1001  = 0x19   shift right 3: ÷ 8 (25)
Careful: Do not confuse & with && or | with ||. 6 & 1 is 0 (bitwise), but 6 && 1 is 1 (logical). Also remember precedence: & | ^ bind LOWER than == and !=, so x & 1 == 0 means x & (1 == 0). Always bracket: (x & 1) == 0.

Shifts in detail

  • x << n fills with zeros on the right; for unsigned x it equals x × 2^n (modulo the type size).
  • x >> n for unsigned x fills with zeros on the left (a logical shift) and equals x / 2^n.
  • Right-shifting a negative signed value is implementation-defined (most compilers copy the sign bit: an arithmetic shift).
  • Left-shifting a negative value, or shifting a 1 into or past the sign bit of a signed int, is undefined behaviour.
  • Shifting by a negative amount or by >= the width of the type (x << 32 for a 32-bit int) is undefined behaviour.
c
unsigned int one_mb = 1u << 20;        /* 1048576: the u suffix makes it unsigned */
uint64_t big = 1ull << 40;              /* a 64-bit shift: plain 1 << 40 would be undefined (int is 32 bits) */

Classic bit tricks

c
int is_odd(unsigned x)          { return x & 1u; }
int is_power_of_two(unsigned x) { return x != 0 && (x & (x - 1)) == 0; }   /* 8 = 1000, 7 = 0111 → 0 */
unsigned clear_lowest(unsigned x) { return x & (x - 1); }

int popcount(unsigned x) {        /* count the 1 bits */
    int n = 0;
    while (x) { x &= x - 1; n++; } /* each step removes the lowest set bit */
    return n;
}
/* GCC/Clang also provide __builtin_popcount; C23 adds stdc_count_ones in <stdbit.h> */
Think of it like this: Bits are like a row of light switches on a wall. AND with a mask is like checking which of certain switches are on; OR turns specific switches on; XOR flips them; shifting moves every switch's position along the row, multiplying or dividing the number by two each step.
Tip: Practise converting between binary, hex and decimal for 8-bit values until it is automatic. Embedded and networking interviews almost always include a few bit questions.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Bitwise operators · 1/6

Bitwise operators

In this lesson you will work with individual bits.

Prefer a video by a teacher? Find free videos on “c bitwise operators and or xor shift tutorial bit tricks” on YouTube ↗

In real life: Packing an RGB colour

A display driver on a smart-watch stores a colour as one 16-bit number in RGB565 format: 5 bits red, 6 bits green, 5 bits blue. Shifts and masks pack the three values into one number and unpack them again.

c
#include <stdint.h>
uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b) {
    return (uint16_t)(((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
}
/* rgb565(255, 255, 255) → 0xFFFF; rgb565(255, 0, 0) → 0xF800 */

Practice (0/3 done)

Task 1 · Question

What is 0x0F | 0xF0?

Task 2 · Code · Javascript

JavaScript has the same bitwise operators (& | ^ ~ << >> and the unsigned shift >>>), working on 32-bit integers, so the same algorithms run here. Write popcount(x) that counts the 1 bits of a non-negative 32-bit number using the x & (x - 1) trick, and isPowerOfTwo(x).

Task 3 · Question

unsigned x = 6; What is (x & 1) == 0 ? "even" : "odd" , and what would x & 1 == 0 (no brackets) compute?

Quick quiz

Question 1

1.What is 5 ^ 3?

Question 2

2.What is 1u << 10?

Question 3

3.Why use unsigned types for bit manipulation?

Question 4

4.What does x & (x - 1) do?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is 5 ^ 3?

Answer: 6

101 ^ 011 = 110 = 6.

What is 1u << 10?

Answer: 1024

2^10.

Why use unsigned types for bit manipulation?

Answer: Shifts and overflow are well defined for unsigned types

Signed shifts have implementation-defined or undefined cases.

What does x & (x - 1) do?

Answer: Clears the lowest set bit of x

Used in popcount and power-of-two tests.

Which expression clears bit 5 of x?Related

Answer: x &= ~(1u << 5)

AND with a mask that has a 0 only at bit 5.

From Masks and flags

Items are [a, b, c] and bit i stands for item i. Which subset does mask 5 (binary 101) mean?Related

Answer: [a, c]

Bits 0 and 2 are set, so items 0 and 2: a and c.

From Bit tricks in interviews

How many bits are in one octet?Related

Answer: 8

An octet is 8 bits. An IPv4 address has 4 octets, so 32 bits.

From Binary and decimal for networking

What type is the result of 3 + 2.0?Related

Answer: double

The int is converted to double.

From Type conversion and casting

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 4 more topics in “Bits, undefined behaviour and safety” before its exam: Masks and flags, Undefined behaviour, Secure and defensive C, Function pointers and callbacks.
  2. Module 9 exam: Bits, undefined behaviour and safety · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Data structures in C. 60 topics left in the course before the final exam.

← Previous: Libraries: static and shared