cppcheck 的 shiftnegativelhs 检查器在左操作数为负数时触发 error 级别告警,消息为“shifting a negative value is undefined behaviour”,用于检测 c/c++ 中对负数执行位移运算的未定义行为。

因为对负数做移位运算是未定义行为(UB),编译器可以生成任意结果,甚至同一段代码在不同优化等级下表现不一致。
cppcheck 会直接报 shiftNegativeLHS 错误
当左操作数(LHS)为负数时,cppcheck 的 shiftNegativeLHS 检查器会触发,消息是“Shifting a negative value is undefined behaviour”。这不是警告,而是 Error 级别问题,必须修复。
- 典型触发场景:
int x = -5; auto y = x —— 即使你只关心低 32 位,<code>x是负的,就已 UB - 注意:不是只有
才有问题,<code>>>对负数同样 UB(尽管很多平台实际做算术右移,但标准不保证) - 即使你用
unsigned int接收结果,也无法绕过 LHS 为负带来的 UB;移位动作本身已在未定义阶段执行
整数提升会让 uint8_t / char 等类型悄悄变负
小整型参与移位时会先提升为 int,而 int 是有符号的——这很容易让原本“安全”的无符号值变成负数。
- 例如:
uint8_t b = 0x80; auto v = b → 实际执行的是 <code>(int)b ,即 <code>128 ,在 <code>int中就是 -2147483648 - 这个 -2147483648 是负数,所以
运算的左操作数是负的 → UB - 修复方法不是加 cast,而是先转成足够宽的无符号类型:
static_cast<uint32_t>(b) </uint32_t>
C++20 也没解决负数 LHS 的问题
C++20 明确了“移位量 ≥ 位宽”时结果为 0,也统一了无符号数移位的语义,但对“左操作数为负”依然保持未定义。
int a = -1; a 在 C++20 下仍是 UB,不能依赖它等于 -2 或其他任何值- 不要试图用条件判断“是否为负”再分支移位——逻辑本身已不可靠,且增加运行时开销
- 真正安全的做法:确保左操作数类型为无符号,或显式转为无符号后再移位,如
static_cast<uint32_t>(x) </uint32_t>
最容易被忽略的一点:UB 不一定当场 crash,它可能让编译器在 -O2 下把整条表达式优化掉、替换成常量、甚至影响周边代码逻辑。一旦出现,调试成本远高于预防成本。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











