【问题标题】:Most efficient portable overflow detection? [duplicate]最有效的便携式溢出检测? [复制]
【发布时间】:2010-07-11 21:05:33
【问题描述】:

在接近 C、C++ 和 D 等金属语言的情况下,检测无符号溢出的最有效的合理可移植方式是什么(即不使用汇编程序,尽管您可能会假设二进制补码算术和环绕行为) 64位整数乘法?

【问题讨论】:

  • C 和 C++ 完全指定了无符号类型的环绕行为,而二进制补码与此类类型无关。
  • @Mark:C99 很好。我主要对 D 感兴趣,但我将 C 和 C++ 放在问题中,因为对它们的任何答案都可能适用于 D。
  • @dscimcha:如果你明确表示你想要 D 的答案,而不仅仅是任何类似 C 的语言,你 a) 会得到你可以使用的答案 b) 你的问题不会'还没有作为副本关闭。
  • @Mark:我认为不拒绝 C/C++ 答案更有意义,因为 C 和 C++ 比 D 更受欢迎,并且在整数等低级内容方面非常相似。

标签: c++ c integer overflow d


【解决方案1】:

您可以通过将无符号类型可表示的最大值除以其中一个被乘数来提前检测溢出;如果结果小于另一个被乘数,则将它们相乘将导致值超出无符号类型的范围。

例如,在 C++ 中(使用 C++0x 精确宽度数字类型):

std::uint64_t left = 12;
std::uint64_t right = 42;

if (left != 0 && (std::numeric_limits<std::uint64_t>::max() / left) < right)
{
    // multiplication would exceed range of unsigned
}

在 C 中,您可以使用 uint64_t 作为类型,使用 UINT64_MAX 作为最大值。或者,如果您只关心类型是至少 64 位宽而不一定完全 64 位宽,您可以使用unsigned long longULLONG_MAX

【讨论】:

    【解决方案2】:

    almost duplicate question 中有几个答案。 This answer 应该可以在 C、C++ 和其他类似语言中工作:

    if (b > 0 && a > 18446744073709551615 / b) {
         // overflow handling
    } else {
        c = a * b;
    }
    

    this answer 执行乘法,然后将结果除以其中一个参数,看看它是否等于另一个:

    x = a * b;
    if (a != 0 && x / a != b) {
        // overflow handling
    }
    

    【讨论】:

    • 我会使用 宏 (c) 或 std::numeric_limits::max (C++) 指定的已用类型的最大值,而不是 18446744073709551615。
    【解决方案3】:

    可能有更有效的方法,但这是一种简单且可移植的方法:

    // assume 'a' and 'b' are the operands to be multiplied
    if( ( a != 0 ) && ( UINT64_MAX / a ) < b ) ) {
      // overflow
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-12
      • 1970-01-01
      • 2012-06-07
      • 1970-01-01
      相关资源
      最近更新 更多