当前位置: 首页 > 知识库问答 >
问题:

整数除法溢出

计胤
2023-03-14

我一直在考虑整数(int类型)溢出,我突然想到除法可能溢出。

示例:在我当前的平台上

INT_MIN == -INT_MAX - 1

因此

INT_MIN < -INT_MAX

因此

INT_MIN / -1 > -INT_MAX / -1

因此

INT_MIN / -1 > INT_MAX.

因此,除法 (INT_MIN / -1 ) 确实溢出。

因此,我有两个问题:

>

  • 可以编写哪些(跨平台)C代码来防止除法溢出(对于类型(有符号)int)?

    什么保证(在C或C标准中)可能有助于设计代码?

    例如,如果标准保证我们有

    INT_MIN == -INT_MAX - 1
    

    或者

    INT_MIN == -INT_MAX,
    

    然后出现以下代码来防止溢出。

    #include <limits.h>
    
    /*
          Try to divide integer op1 by op2.
          Return
            0 (success) or
            1 (possibly overflow prevented).
          In case of success, write the quotient to res.
    */
    
    int safe_int_div(int * res, int op1, int op2) {
    
      /*   assert(res != NULL);   */
      /*   assert(op2 != 0);      */
    
      if ( op1 == INT_MIN && op2 == -1 )  {
        return 1;
      }
      *res = op1 / op2;
      return 0;
    }
    
  • 共有2个答案

    龙越彬
    2023-03-14

    1)正如C中的任何其他操作一样,应用程序必须确保:

      < li >用于计算本身的类型足够大,并且 < li >存储结果的变量类型足够大。

    确保这一点的方法是在运算之前设置每个操作数的大小限制。什么样的限制是合适的取决于算法和变量的目的。

    2)如果你使用C标准的stdint.h,你可以保证变量有多大。在编写可移植代码时,永远不要使用< code>int。

    至于编写安全除法例程的情况,它将以32位整数作为参数,然后对64位整数执行计算并将结果作为32位整数返回。

    #include <stdint.h>
    #include <stdbool.h>
    
    /*
          Try to divide integer op1 by op2.
          Return
            true (success) or
            false (possibly overflow prevented).
          In case of success, write the quotient to res.
          In case of failure, res remains untouched.
    */
    
    bool safe_int_div (int32_t* res, int32_t op1, int32_t op2) {
    
      if(op2 == 0)
        return false;
    
      int64_t res64 = (int64_t)op1 / (int64_t)op2;
    
      if(res64 > INT32_MAX || res64 < INT32_MIN)
        return false;
    
      *res = (int32_t)res64_t;
    
      return true;
    }
    

    如果需要有关除法失败原因的更多信息,请将bool替换为枚举。

    梁骞仕
    2023-03-14

    什么保证(在C或C标准中)可能有助于设计代码?

    C 使用 3 种形式中的 1 种指定有符号整数表示形式:符号和大小、二的补码或 1 的补码。给定这些形式,只有除以 0 和 2 的补码除以 INT_MIN/-1 可能会溢出。

    为了防止除法溢出(对于(有符号的)int类型),可以编写什么样的(跨平台)C代码?

    int safe_int_div(int * res, int op1, int op2) {
      if (op2 == 0) {
        return 1;
      }
      // 2's complement detection
      #if (INT_MIN != -INT_MAX) 
        if (op1 == INT_MIN && op2 == -1)  {
          return 1;
        }
      #endif
      *res = op1 / op2;
      return 0;
    }
    
     类似资料:
    • 虚拟机安装:Ubuntu 12.04(x86) 什么是整数溢出? 存储大于最大支持值的值称为整数溢出。整数溢出本身不会导致任意代码执行,但整数溢出可能会导致堆栈溢出或堆溢出,这可能导致任意代码执行。在这篇文章中,我将仅谈论整数溢出导致堆栈溢出,整数溢出导致堆溢出将在后面的单独的帖子中讨论。 数据类型大小及范围: 当我们试图存储一个大于最大支持值的值时,我们的值会被包装 。例如,当我们尝试将存储到带

    • 本文向大家介绍C#整数溢出,包括了C#整数溢出的使用技巧和注意事项,需要的朋友参考一下 示例 整数可以存储的最大容量。而当您超过该限制时,它将循环回到负面。对于int,它是2147483647 对于超出此范围的所有整数,请使用System.Numerics数据类型为BigInteger的名称空间。检查下面的链接以获取更多信息https://msdn.microsoft.com/zh-cn/libr

    • 我在一次采访中被问及这一点。我被要求计算数字x1,x2,x3,…的平均值,。。。xn公司 //所以归结起来是这样的: 面试官说列表的大小是未知的,它可能很大,所以总和可能会溢出。他问我如何解决溢出问题,我的回答是跟踪我们可能超过最大数量的次数等等,他说了一些关于推入堆栈、平均值和长度的事情,我从来没有真正理解他的解决方案,将这两个变量推入某种列表中?有人知道吗?

    • 这是LeetCode中的Pascal三角形编码问题,它要求输出Pascal三角形的第n行。使用,输出如下所示: 显然存在溢出问题。现在为了解决这个问题,我修改了行< code > result . push _ back(result[I-1]*(rowIndex 1-I)/I);到< code > result . push _ back((double)result[I-1]*(double)

    • 由于溢出,下面代码中的第一个for循环找不到正确的最大值。然而,第二个for循环确实如此。我用了门闩。com查看该程序的字节码,该程序显示,要确定哪个数字更大,第一个for循环使用isub,第二个for循环使用if_icmple。有道理。然而,为什么if_icmple能够成功地进行这种比较,因为它在某些时候也必须进行减法运算(我认为这会产生溢出)? 输出是 最大值为-2147483648

    • 我正在简单的C程序中试验无符号int数据类型和主方法参数。作为一个实验,我写了一个程序,从命令行获取一个int数作为main方法的参数,并对该数和0之间的每个整数求和。 例如,程序计算 f(n) = (1 2 3... n) 当 n 时有效 我开始注意到的第一件事是当f(n) 我手动发现数学上的最大值,我的程序生成的结果将是有效的(例如,在整数溢出之前),对于有符号整数为65535,对于无符号in