C++20stladvanced
std::countl_zero / std::countl_one (C++20 Addition)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
`countl_zero` counts the number of consecutive zero bits starting from the most significant bit. `countl_one` counts consecutive one bits from the MSB. Useful for priority encoding and normalization.
Real-World Scenario
Implement a fast priority encoder that finds the highest-priority set bit in an interrupt status register.
Quick Snippet
snippet.cpp
#include <bit>
#include <cstdint>
uint32_t flags = 0b00001000'00000000'00000000'00000000;
auto leading_zeros = std::countl_zero(flags); // 4
auto leading_ones = std::countl_one(~flags); // 4Full Example
countl.cpp
// CodeNebula - C++20 Example: std::countl_zero and std::countl_one
// Compile: g++ -std=c++20 -Wall -Wextra -o example countl.cpp
#include <bit>
#include <bitset>
#include <cstdint>
#include <iostream>
template <typename T>
void show_countl(T val) {
constexpr int bits = sizeof(T) * 8;
std::cout << " " << std::bitset<bits>(val)
<< " (" << static_cast<uint64_t>(val) << ")"
<< " countl_zero=" << std::countl_zero(val)
<< " countl_one=" << std::countl_one(val) << "\n";
}
int main() {
std::cout << "=== std::countl_zero - count leading zeros ===\n";
std::cout << "(Counts consecutive 0-bits from the most significant bit)\n\n";
// 8-bit examples for clarity
std::cout << "uint8_t examples:\n";
show_countl(static_cast<uint8_t>(0)); // 8 leading zeros
show_countl(static_cast<uint8_t>(1)); // 7 leading zeros
show_countl(static_cast<uint8_t>(2)); // 6 leading zeros
show_countl(static_cast<uint8_t>(127)); // 1 leading zero
show_countl(static_cast<uint8_t>(128)); // 0 leading zeros
show_countl(static_cast<uint8_t>(255)); // 0 leading zeros
std::cout << "\n=== std::countl_one - count leading ones ===\n";
std::cout << "(Counts consecutive 1-bits from the most significant bit)\n\n";
std::cout << "uint8_t examples:\n";
show_countl(static_cast<uint8_t>(0xFF)); // 8 leading ones
show_countl(static_cast<uint8_t>(0xFE)); // 7 leading ones
show_countl(static_cast<uint8_t>(0xF0)); // 4 leading ones
show_countl(static_cast<uint8_t>(0xC0)); // 2 leading ones
show_countl(static_cast<uint8_t>(0x80)); // 1 leading one
show_countl(static_cast<uint8_t>(0x00)); // 0 leading ones
std::cout << "\n=== 32-bit examples ===\n";
std::cout << "countl_zero(0u) = " << std::countl_zero(0u) << "\n";
std::cout << "countl_zero(1u) = " << std::countl_zero(1u) << "\n";
std::cout << "countl_zero(0x7FFFFFFFu) = " << std::countl_zero(0x7FFFFFFFu) << "\n";
std::cout << "countl_zero(0xFFFFFFFFu) = " << std::countl_zero(0xFFFFFFFFu) << "\n";
std::cout << "\n=== Practical: fast log2 ===\n";
for (unsigned v : {1u, 2u, 4u, 8u, 16u, 100u, 1024u}) {
int log2 = 31 - std::countl_zero(v);
std::cout << "floor(log2(" << v << ")) = " << log2 << "\n";
}
std::cout << "\n=== Practical: subnet mask validation ===\n";
// Valid subnet masks have all 1s followed by all 0s
uint32_t masks[] = {0xFFFFFF00, 0xFFFFF000, 0xFFFF0000, 0xFFF0FF00};
for (auto mask : masks) {
int ones = std::countl_one(mask);
int zeros = std::countl_zero(static_cast<uint32_t>(~mask));
bool valid = (ones + (32 - ones)) == 32 && ones == zeros;
std::cout << "Mask 0x" << std::hex << mask << std::dec
<< ": leading ones=" << ones
<< " valid=" << (valid ? "yes" : "no") << "\n";
}
return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example countl.cpp