n > 0 && (n & (n - 1)) == 0 是判断2的幂最稳妥写法,因裸用 n & (n - 1) == 0 会误判0和负数;unsigned类型仍需 n != 0;int_min需转unsigned防溢出;log2和除2法有精度与性能问题。

为什么 n & (n - 1) == 0 不够用
单独写 n & (n - 1) == 0 会把 0 判为 2 的幂——实际不是,而且 0 & -1 在补码下常得 0,直接返回 true;负数如 -4 也会算出 0(因符号位参与运算),但数学上 2 的幂恒为正整数。所以这个表达式必须配合前置条件,不能裸用。
int 类型下最稳妥的写法
对有符号整数,必须显式排除非正数:
-
n > 0是硬性前提,不可省略 -
(n & (n - 1)) == 0必须加括号,否则n & n - 1等价于(n & n) - 1,结果全错 - 完整函数示例:
bool isPowerOfTwo(int n) { return n > 0 && (n & (n - 1)) == 0; }
用 unsigned int 能省掉 n > 0 吗
不能。虽然 unsigned 下 n - 1 对 0 回绕成全 1(如 0U - 1U == UINT_MAX),导致 0U & UINT_MAX == 0,仍会误判。所以即使换类型,n != 0 仍要写:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 推荐统一写法:
n != 0 && (n & (n - 1)) == 0 - 若输入可能含
INT_MIN(如 -2147483648),n - 1会溢出未定义行为,此时应先转unsigned再判断
比位运算更慢的替代方案有哪些坑
std::log2(n) 和循环除 2 都不推荐:
std::log2(1LL 在某些平台会因浮点精度丢一位,<code>floor后再pow(2, ...)可能不等于原值- 循环写法需处理
n % 2 != 0和n == 1两个退出分支,O(log n) 时间,且分支预测失败时 CPU 流水线易 stall - 位运算无分支、无浮点、单条指令,编译器通常直接映射为
and或test指令
真正容易被忽略的是:这个“一行判断”在模板泛型代码里,若传入 char 或 short,提升后可能改变行为;跨平台时,int 位宽不一致也会影响边界值处理——别只盯着公式,得盯住类型和上下文。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










