添加签名到无符号时如何判断溢出

rog*_*erz 9 c unsigned signed overflow underflow

我在向无符号位置添加有符号偏移时尝试检测溢出

uint32 position;
int32 offset;  // it could be negative
uint32 position = position+offset;
Run Code Online (Sandbox Code Playgroud)

如何检查结果是溢出还是下溢?

我想到了一个丑陋的方式,但不确定它的正确性.

  • 下溢: offset < 0 && position + offset >= position
  • 溢出: offset > 0 && position + offset <= position

而且我也想知道是否有一种更优雅的方式来做到这一点.

更新:

如果偏移很长,最好的解决方案是什么?

uint32 position;
long offset;  // it could be negative
uint32 position = position+offset;
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 1

您的测试是正确的。我现在没有看到更优雅的方式,也许没有。

为什么条件是正确的:算术运算uint32_t是模 2^32 的算术运算。int32_t从到 的转换uint32_t通常是对位模式的重新解释(无论如何,正如 @caf 指出的,这里它是模 2^32 的缩减,所以它肯定有效)。将positionoffset视为任意精度整数。当且仅当 时才会发生溢出
position + offset >= 2^32。但是offset < 2^31, so position + offset < position + 2^31,小于position + 2^32,下一个减少到position模 2^32 的值,所以 as uint32_t,then position + offset < position。另一方面,如果offset > 0position + offset < position,显然发生了溢出。当且仅当position + offset < 0作为数学整数时才会发生下溢。因为offset >= -2^31,类似的推理表明,当且仅当 时才会发生下溢offset < 0 && position + offset > position

  • 负数到无符号的转换*不是*实现定义的 - 它以比无符号类型中可表示的最大值大的模数 1 进行减少。这是由标准保证的。 (2认同)