Files
dsa-competitive-programming/leetcode/lc401/notes.md
T

4.2 KiB
Raw Blame History

C++ Bit Manipulation Reference

This document contains:

  • GCC / Clang built-in bit functions
  • C++20 <bit> header utilities
  • C++23 additions

Part 1 — GCC / Clang Built-in Bit Functions

These are compiler-specific (GCC / Clang). They are fast (usually O(1)) and often map to CPU instructions.


1. __builtin_popcount

Counts number of set bits (1s).

Variants

__builtin_popcount(x)     // → int
__builtin_popcountl(x)    // → long
__builtin_popcountll(x)   // → long long

Example

int x = 13; // 1101
int cnt = __builtin_popcount(x); // 3

2. __builtin_clz

Count Leading Zeros (from MSB).

Variants

__builtin_clz(x)
__builtin_clzl(x)
__builtin_clzll(x)

Example

int x = 8; // 000...1000
int zeros = __builtin_clz(x); // 28 (32-bit int)

Notes

⚠️ Undefined if x == 0

// Highest set bit index:
int highest = 31 - __builtin_clz(x);

3. __builtin_ctz

Count Trailing Zeros (from LSB).

Variants

__builtin_ctz(x)
__builtin_ctzl(x)
__builtin_ctzll(x)

Example

int x = 8; // 1000
int zeros = __builtin_ctz(x); // 3

⚠️ Undefined if x == 0


4. __builtin_parity

Returns 1 if odd number of set bits, 0 if even.

int x = 7; // 111
int p = __builtin_parity(x); // 1

5. __builtin_ffs

Find First Set Bit (1-indexed from right). Returns 0 if input is 0.

int x = 10; // 1010
int pos = __builtin_ffs(x); // 2

Part 2 — C++20 <bit> Header (Portable Standard)

#include <bit>

Works on unsigned integer types only.


1. std::popcount

Counts number of set bits.

std::popcount(x);

2. std::countl_zero

Count leading zeros. Safe for x == 0 (returns bit width).

std::countl_zero(x);

3. std::countl_one

Count consecutive leading ones.

std::countl_one(x);

4. std::countr_zero

Count trailing zeros. Safe for x == 0 (returns bit width).

std::countr_zero(x);

5. std::countr_one

Count consecutive trailing ones.

std::countr_one(x);

6. std::has_single_bit

Returns true if exactly one bit is set (i.e., power of 2).

std::has_single_bit(x);

// Equivalent to:
x > 0 && (x & (x - 1)) == 0;

7. std::bit_width

Number of bits required to represent x.

std::bit_width(x);

// Equivalent to (for x > 0):
floor(log2(x)) + 1;

8. std::bit_floor

Largest power of 2 ≤ x.

std::bit_floor(x);

// Example:
std::bit_floor(10); // → 8

9. std::bit_ceil

Smallest power of 2 ≥ x.

std::bit_ceil(x);

// Example:
std::bit_ceil(10); // → 16

10. std::rotl — Rotate Left

Circular left rotation.

std::rotl(x, s);

11. std::rotr — Rotate Right

Circular right rotation.

std::rotr(x, s);

Part 3 — C++23 Additions


1. std::byteswap

Swap byte order (endianness conversion).

std::byteswap(x);

// Example:
// 0x12345678 → 0x78563412

2. std::endian

Detect system byte order.

#include <bit>

if (std::endian::native == std::endian::little) {
    // little-endian system
}

Applications

A number of the form 1 << k has a one bit in position k and all other bits are zero, so we can use such numbers to access single bits of numbers. In particular, the kth bit of a number is one exactly when x & (1 << k) is not zero. The following code prints the bit representation of an int number x:

for (int i = 31; i >= 0; i--) {
if (x&(1<<i)) cout << "1";
else cout << "0";
}

It is also possible to modify single bits of numbers using similar ideas. For example, the formula x | (1 << k) sets the kth bit of x to one, the formula x & ~(1 << k) sets the kth bit of x to zero, and the formula x ^ (1 << k) inverts the kth bit of x. The formula x & (x 1) sets the last one bit of x to zero, and the formula x & x sets all the one bits to zero, except for the last one bit. The formula x | (x 1) inverts all the bits after the last one bit. Also note that a positive number x is a power of two exactly when x & (x 1) = 0.