【发布时间】:2011-12-02 18:40:01
【问题描述】:
这可能是一个菜鸟问题,但是如何检查一些溢出影响了我在 C 中的数字的值。例如,当乘以整数并等待整数结果时,如果实际结果大于最大整数值,实际结果被改变了(对吧?)。那么如何判断是否发生了这样的事情呢?
【问题讨论】:
-
所谓的“重复”问题专门针对 unsigned 值,答案反映了这一点 - 而这个问题更笼统,涵盖了更棘手的签名案例。
这可能是一个菜鸟问题,但是如何检查一些溢出影响了我在 C 中的数字的值。例如,当乘以整数并等待整数结果时,如果实际结果大于最大整数值,实际结果被改变了(对吧?)。那么如何判断是否发生了这样的事情呢?
【问题讨论】:
有符号整数溢出就像除以零 - 它会导致未定义的行为,因此您必须检查它是否会在执行潜在溢出操作之前发生。一旦你溢出,所有的赌注都没有了——你的代码可以做任何事情。
<limits.h> 中定义的 *_MAX 和 _MIN 宏可以为此派上用场,但您需要注意不要在测试本身中调用未定义的行为。例如,要检查给定a * b 是否会溢出int a, b;,您可以使用:
if ((b > 0 && a <= INT_MAX / b && a >= INT_MIN / b) ||
(b == 0) ||
(b == -1 && a >= -INT_MAX) ||
(b < -1 && a >= INT_MAX / b && a <= INT_MIN / b))
{
result = a * b;
}
else
{
/* calculation would overflow */
}
(请注意,这避免了一个微妙的陷阱是您无法计算 INT_MIN / -1 - 这样的数字不能保证是可表示的,并且确实会导致常见平台上的致命陷阱。
【讨论】:
C99 标准有这部分解释什么是未定义的行为:
3.4.3
未定义的行为
行为,在使用不可移植或错误的程序构造或错误数据时, 本国际标准没有要求的 注意 可能的未定义行为包括完全无视情况和不可预测 结果,在翻译或程序执行期间以文件的方式表现 环境(无论是否发出诊断消息),终止翻译或 执行(发出诊断消息)。
示例
未定义行为的一个示例是整数溢出行为。
所以你很不走运,在一般情况下,事后没有便携的方法来检测它。
不过,您的编译器/实现可能对其进行了扩展/支持,并且有一些技术可以避免这些情况。
请参阅此问题以获得出色的建议:Best way to detect integer overflow in C/C++。
【讨论】:
如果您的意思是在编程时,您可以调试代码。
如果您的意思是在运行时,您可以添加一些条件,如果超出限制,则执行某些操作。
当计算的产量超出范围时,C 不知道该怎么做。您必须通过测试操作数来规避这一点。
【讨论】:
检查此http://www.fefe.de/intof.html。它向您展示了如何检查实际结果是否大于最大整数值。
【讨论】:
如果结果数小于输入之一。
a + b = c,如果 c 溢出。 编辑:要快,这仅适用于无符号整数的加法。
【讨论】:
在一般情况下,您无法仅通过盯着结果来知道是否发生溢出。但是,您可以做的是单独检查操作是否会溢出。例如。如果要检查 a*b 是否溢出,其中 a 和 b 是 int 的,则需要解决不等式
<pre>a * b <= INT_MAX</pre>
也就是说,如果a
【讨论】:
b 时,如果b 为负数,则必须翻转不等式。另外,不要忘记b == 0 的可能性。
只要您在无符号整数中进行算术运算,或者可以依赖特定于实现的保证来了解有符号整数溢出的行为,您就可以使用各种技巧。
在无符号乘法的情况下,最简单的是:
unsigned int lhs = something, rhs = something_else;
unsigned int product = lhs * rhs;
if (lhs != 0 && product/lhs != rhs) { overflow occurred }
它不太可能很快,但它是便携的。加法的无符号溢出检查也很简单——选择任一操作数,当且仅当总和小于该值时才会发生溢出。
【讨论】: