__builtin_popcount最快,它直接映射到cpu的popcnt指令,单周期完成;但仅gcc/clang支持,msvc不兼容,且必须传入无符号类型,否则负数会因补码解释导致结果错误。

用 __builtin_popcount 最快,但只在 GCC/Clang 有效
GCC 和 Clang 提供了内置函数 __builtin_popcount(对 unsigned int)和 __builtin_popcountll(对 unsigned long long),底层直接映射到 CPU 的 POPCNT 指令,单周期完成,性能碾压手动循环。但注意:MSVC 不支持,跨平台项目里硬写会编译失败。
常见误用是传入有符号数——比如 int x = -1;,传给 __builtin_popcount(x) 会把负数按补码解释为很大的正整数,结果不是你想要的“-1 的二进制表示里有几个 1”。务必先转成无符号类型:
int x = -1; std::cout (x)); // 正确:输出 32(在 32 位 int 下)
- 仅限 GCC/Clang;MSVC 请改用
std::popcount(C++20)或手动实现 - 参数必须是无符号整型,否则行为未定义
- 对
char或short传参会自动提升,但建议显式转换避免歧义
C++20 的 std::popcount 是标准且安全的选择
std::popcount 在 <bit></bit> 头文件中,要求参数为无符号整型(unsigned char、unsigned int 等),编译器会在支持时自动用硬件指令,不支持时回退为高效查表或位运算,语义清晰、可移植性强。
它拒绝有符号类型,编译期就报错,比 __builtin_popcount 更安全:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
#include <bit>
unsigned int x = 0b1011;
std::cout <ul>
<li>必须包含 <code><bit></bit></code>,且编译器需开启 C++20 支持(如 <code>-std=c++20</code>)</li>
<li>不接受 <code>int</code>、<code>long</code> 等有符号类型,连隐式转换都不行</li>
<li>对 <code>unsigned long long</code> 同样有效,无需额外后缀</li>
</ul>
<h3>手动实现:n & (n-1) 清零最低位 1,适合教学或嵌入式环境</h3>
<p>这个技巧利用了位运算特性:对任意非零整数 <code>n</code>,<code>n & (n-1)</code> 会把 <code>n</code> 的二进制表示中最右边的 1 变成 0。循环执行直到 <code>n == 0</code>,循环次数就是 1 的个数。时间复杂度是 O(1)(最多 32 或 64 次),比逐位检查快一倍。</p>
<pre class="brush:php;toolbar:false;">int count_bits(unsigned int n) {
int cnt = 0;
while (n) {
n &= n - 1;
++cnt;
}
return cnt;
}
- 输入必须是无符号类型,否则
n-1对负数可能溢出或逻辑异常 - 相比查表法,空间占用为 O(1),适合内存受限场景
- 比
n >>= 1; cnt += n & 1;少做很多次移位和与操作,尤其当 1 很少时优势明显
为什么不能直接用 std::bitset(n).count()?
虽然 std::bitset::count() 语义直观,且标准库保证高效实现,但它有隐藏开销:构造 std::bitset 需要复制和初始化整个位容器,对高频调用(如图像处理像素遍历)可能成为瓶颈。而且模板大小必须在编译期确定,无法适配运行时才知道位宽的场景(比如处理 uint64_t 但只关心低 24 位)。
- 每次调用都触发对象构造/析构,哪怕优化后也可能残留少量指令
- 位宽写死(如
bitset),对long long需手动改成bitset,易出错 - 在 constexpr 上下文中,
std::popcount支持编译期计算,bitset::count则不一定(取决于实现)
C++ 统计 1 的个数没有唯一“最佳”方案,关键看你的编译器、标准版本和性能敏感度。最易踩的坑是忽略有符号/无符号类型差异,以及在跨平台项目中盲目依赖编译器内置函数。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










