3

我在网站上看到了多个解决无符号整数上溢/下溢的问题。大多数关于下溢的问题都涉及将负数分配给无符号整数。我不清楚的是当unsigned int从另一个中减去一个时会发生什么,unsigned int例如a - b结果是否定的。该标准的相关部分是:

涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果会以比结果类型可以表示的最大值大一的数字为模减少。

在这种情况下,您如何解释“减少”?这是否意味着将UINT_MAX+1添加到否定结果中,直到它是>= 0

我看到这个问题解决了要点(基本上说标准选择谈论溢出,但关于的要点也适用于下溢)但我仍然不清楚:

说结果a-b-1;根据标准,操作-1%(UINT_MAX+1)将返回(如此-1解释);所以我们回到了我们开始的地方。

这可能过于迂腐了,但是这个是否意味着数学模而不是 C 的计算模?

4

3 回答 3

5

首先,低于给定整数类型最小值的结果在 C 中不称为“下溢”。术语“下溢”是为浮点类型保留的,意味着完全不同的东西。超出整数类型的范围总是溢出,无论您跨越范围的哪一端。因此,在这种情况下,您没有看到语言规范谈论“下溢”执行者这一事实并没有任何意义。

其次,您对“减少”一词的含义是绝对正确的。最终值是通过UINT_MAX+1从“数学”结果中加(或减)来定义的,直到它返回到unsigned int. 这也与欧几里得“模”运算相同。

于 2018-06-17T22:11:23.943 回答
1

您发布的标准部分谈论溢出,而不是下溢。

“这是否意味着将 UINT_MAX+1 添加到负结果中,直到 >= 0?”

你可以认为这就是发生的事情。抽象的结果将是相同的。已经有人问过类似的问题。检查此链接:有关无符号整数下溢的 C 行为的问题以获取更多详细信息。

另一种思考方式是,例如,-1 原则上来自类型int(即 4 个字节,其中所有位均为 1)。然后,当您告诉程序将所有这些位 1 解释为unsigned int时,其值将被解释为UINT_MAX

于 2018-06-17T21:45:27.350 回答
0

在幕后,加法或减法是按位计算的,并且与符号无关。生成的代码可以使用相同的指令,而不管它是否签名。解释结果的是其他运算符,例如 a > 0。按位加或减,这会告诉你答案。b0 - b1 = b111111111 答案是相同的,与符号无关。只有其他运算符将答案视为有符号类型的 -1 和无符号类型的 0xFF。该标准描述了这种行为,但我总是发现最容易记住它是如何工作的,并推断出我正在编写的代码的后果。

signed int adds(signed int a, signed int b)
{
    return a + b;
}

unsigned int addu(unsigned a, unsigned b)
{
    return a + b;
}


int main() {
    return 0;
}

->

adds(int, int):
  lea eax, [rdi+rsi]
  ret
addu(unsigned int, unsigned int):
  lea eax, [rdi+rsi]
  ret
main:
  xor eax, eax
  ret
于 2018-06-18T13:43:12.107 回答