判断整数n第k位是否为1的核心方法是(n & (1

用 & 和移位判断某一位是否为 1
核心方法是:把目标位移到最低位,再和 1 做按位与。如果结果非零,说明该位是 1。
假设要判断整数 n 的第 k 位(从 0 开始计数,即最低位是第 0 位),最常用写法是:
bool is_set = (n & (1 <p>这里 <code>1 生成一个只有第 <code>k</code> 位为 1 的掩码,<code>&</code> 操作会清零其他所有位,只保留第 <code>k</code> 位的原始值。注意括号不能省——<code>&</code> 优先级低于 <code>,不加括号会导致逻辑错误。</code></code></p>
- 对无符号类型(如
uint32_t)最安全;对有符号类型,需确保n非负,否则右移或高位行为可能因编译器而异 -
k必须小于类型总位数(如int通常是 32 位),否则1 可能溢出,结果未定义 - 不要写成
(n >> k) & 1—— 虽然等价,但对负数做算术右移时,高位补的是符号位,可能让结果意外为1
处理负数时为什么推荐用无符号类型
有符号整数右移是「算术右移」,C++ 标准允许实现填充符号位。比如 -4 >> 1 在多数平台得 -2,但 -1 >> 1 可能还是 -1(高位补 1),导致 (n >> k) & 1 判断失真。
更稳妥的做法是先转成对应宽度的无符号类型再操作:
uint32_t u = static_cast<uint32_t>(n); bool is_set = (u & (1U <ul> <li>用 <code>1U</code>(无符号字面量)避免左移时发生有符号溢出</li> <li>显式 <code>static_cast</code> 比隐式转换更清晰,也防止窄类型(如 <code>char</code>)提升后位宽不匹配</li> <li>如果 <code>k</code> 来自运行时变量,且可能 ≥32,记得加边界检查,否则 <code>1U 是未定义行为</code> </li> </ul> <h3>用 <code>std::bitset</code> 判断但要注意性能开销</h3> <p>如果只是偶尔判断、代码可读性优先,<code>std::bitset</code> 提供了直观接口:</p> <pre class="brush:php;toolbar:false;">std::bitset b(n); bool is_set = b[k]; // 自动范围检查(debug 模式下抛异常)
- 下标访问
b[k]在 debug 模式下会检查越界,release 模式通常无检查,但仍有构造bitset的开销 - 不适用于泛型场景——模板参数必须是编译期常量,无法适配动态位宽
- 底层仍靠位运算实现,没必要为单次判断引入额外对象和内存布局
常见错误:混淆位序编号方向或误用宏
有人封装成宏,比如 #define BIT_SET(n,k) ((n) & (1 ,看似简洁,但容易踩坑:
- 宏不检查
k是否越界,1 在 32 位系统上直接 UB - 参数
n若是表达式(如i++),宏展开后可能多次求值,引发未定义行为 - 位序理解错:误以为「第 1 位」是最高位(MSB),实际标准是从 LSB(第 0 位)开始编号;通信协议或硬件寄存器文档有时反着标,务必确认上下文
- 用
char或short类型时,左移前没提升到int,1 对 <code>short可能截断
位运算本身很轻量,但位序含义、类型宽度、符号性这三点一旦出错,问题往往隐蔽且难调试。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











