【问题标题】:How to check if overflow occured? [duplicate]如何检查是否发生溢出? [复制]
【发布时间】:2011-12-02 18:40:01
【问题描述】:

可能重复:
Best way to detect integer overflow in C/C++

这可能是一个菜鸟问题,但是如何检查一些溢出影响了我在 C 中的数字的值。例如,当乘以整数并等待整数结果时,如果实际结果大于最大整数值,实际结果被改变了(对吧?)。那么如何判断是否发生了这样的事情呢?

【问题讨论】:

  • 所谓的“重复”问题专门针对 unsigned 值,答案反映了这一点 - 而这个问题更笼统,涵盖了更棘手的签名案例。

标签: c overflow


【解决方案1】:

有符号整数溢出就像除以零 - 它会导致未定义的行为,因此您必须检查它是否会在执行潜在溢出操作之前发生。一旦你溢出,所有的赌注都没有了——你的代码可以做任何事情。

<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 - 这样的数字不能保证是可表示的,并且确实会导致常见平台上的致命陷阱。

【讨论】:

    【解决方案2】:

    C99 标准有这部分解释什么是未定义的行为:

    3.4.3
    未定义的行为
    行为,在使用不可移植或错误的程序构造或错误数据时, 本国际标准没有要求的 注意 可能的未定义行为包括完全无视情况和不可预测 结果,在翻译或程序执行期间以文件的方式表现 环境(无论是否发出诊断消息),终止翻译或 执行(发出诊断消息)。
    示例
    未定义行为的一个示例是整数溢出行为

    所以你很不走运,在一般情况下,事后没有便携的方法来检测它。
    不过,您的编译器/实现可能对其进行了扩展/支持,并且有一些技术可以避免这些情况。
    请参阅此问题以获得出色的建议:Best way to detect integer overflow in C/C++

    【讨论】:

      【解决方案3】:

      如果您的意思是在编程时,您可以调试代码。

      如果您的意思是在运行时,您可以添加一些条件,如果超出限制,则执行某些操作。

      当计算的产量超出范围时,C 不知道该怎么做。您必须通过测试操作数来规避这一点。

      【讨论】:

        【解决方案4】:

        检查此http://www.fefe.de/intof.html。它向您展示了如何检查实际结果是否大于最大整数值。

        【讨论】:

          【解决方案5】:

          如果结果数小于输入之一。

          a + b = c,如果 c 溢出。 编辑:要快,这仅适用于无符号整数的加法。

          【讨论】:

            【解决方案6】:

            在一般情况下,您无法仅通过盯着结果来知道是否发生溢出。但是,您可以做的是单独检查操作是否会溢出。例如。如果要检查 a*b 是否溢出,其中 a 和 b 是 int 的,则需要解决不等式 <pre>a * b &lt;= INT_MAX</pre>

            也就是说,如果a

            【讨论】:

            • 请记住,当您将不等式两边除以b 时,如果b 为负数,则必须翻转不等式。另外,不要忘记b == 0 的可能性。
            【解决方案7】:

            只要您在无符号整数中进行算术运算,或者可以依赖特定于实现的保证来了解有符号整数溢出的行为,您就可以使用各种技巧。

            在无符号乘法的情况下,最简单的是:

            unsigned int lhs = something, rhs = something_else;
            unsigned int product = lhs * rhs;
            
            if (lhs != 0 && product/lhs != rhs) { overflow occurred }
            

            它不太可能很快,但它是便携的。加法的无符号溢出检查也很简单——选择任一操作数,当且仅当总和小于该值时才会发生溢出。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-11-19
              • 2020-08-15
              • 2019-01-23
              • 1970-01-01
              • 2018-12-09
              • 1970-01-01
              • 2017-09-13
              • 1970-01-01
              相关资源
              最近更新 更多