【发布时间】:2018-06-17 20:51:39
【问题描述】:
我在网站上看到了多个解决无符号整数上溢/下溢的问题。
大多数关于 underflow 的问题都涉及将负数分配给无符号整数;我不清楚的是,当从另一个 unsigned int 中减去 unsigned int 时会发生什么,例如a - b 结果是否定的。标准的相关部分是:
涉及无符号操作数的计算永远不会溢出,因为无法由生成的无符号整数类型表示的结果会以比结果类型可以表示的最大值大一的数字为模减少。
在这种情况下,您如何解释“减少”?这是否意味着UINT_MAX+1 被添加到否定结果中,直到它成为>= 0?
我看到this question 解决了要点(基本上说标准选择谈论 overflow 但关于 modulo 的要点适用于下溢太)但我仍然不清楚:
说a-b的结果是-1;根据标准,操作-1%(UINT_MAX+1) 将返回-1(如here 解释);所以我们又回到了开始的地方。
这可能过于迂腐,但 模 是指数学模而不是 C 的计算模吗?
【问题讨论】:
-
不加减,不进行模运算:结果被截断为目的操作数的位数。如果
unsigned类型是32 位,则甚至不存在更多位。但是,32 位乘法的结果在处理器中可能是 64 位,在这种情况下,高 32 位将被忽略。 -
从概念上讲,计算是使用“无限精度”完成的,结果会减少到
0..UINT_MAX范围内的值。 -
@EnzoNakamura 我认为这是误导。该代码不执行任何模运算。结果要么被截断,要么如果没有更多有效位,则允许回绕。整数大小适合处理器寄存器的自然大小,无需任何后处理即可实现。
-
@WeatherVane 就像“不执行模运算:结果被截断为位数”一样,即未指定实现细节。考虑一个没有无符号乘法/除法的 36 位 CPU。这样的平台可以使用 35 位的掩码(实际上是对结果取模) - 并带有 1 个填充位和
LONG_MAX == ULONG_MAX。如今,使用xxx_MAX == Uxxx_MAX的此类机器很少存在,但规范是“产生的无符号整数类型以比结果类型可以表示的最大值大一的数字为模减少”。 -
@NeilEdelman。我不确定你是什么意思。数学模通常是欧几里得模,其中 C 的模 (%) 被截断,请参阅en.wikipedia.org/wiki/Modulo_operation
标签: c integer standards underflow