在递归函数[C]中捕获整数溢出

在递归函数[C]中捕获整数溢出,c,recursion,integer,overflow,C,Recursion,Integer,Overflow,更新: 感谢您的宝贵意见和建议。根据你们所说的,这就是我想到的: #include <limits.h> ... else { int a = binom(n - 1, k - 1); int b = binom(n - 1, k); if(a > 0) { if (b > INT_MAX - a) { // case 1: integer overflow printf(

更新:

感谢您的宝贵意见和建议。根据你们所说的,这就是我想到的:

#include <limits.h>
  ...
  else {
     int a = binom(n - 1, k - 1);
     int b = binom(n - 1, k);
     if(a > 0) {
         if (b > INT_MAX - a) {          // case 1: integer overflow
             printf("int overflow\n");
             return;
         }
     }
     else if (b < INT_MIN - a) {         // case 2: integer overflow
         printf("int overflow\n");
         return;
     }
     int c = a + b;
     return c;
}
在这种逻辑下,我假设捕获应该在递归调用语句中。比如:

如果(binom(n-1,k-1)+binom(n-1,k))导致溢出,返回错误,否则继续执行binom(n-1,k-1)+binom(n-1,k)
执行以下操作:

long res=(long)binom(n - 1, k - 1) + binom(n - 1, k);
if (res>INT_MAX) {
 printf("int overflow\n");
 exit(1);
}
return (int)res;
(假设系统中的
long
int
长。如果不是这样,请使用更宽的类型)

编辑:如果您不想在出现错误时退出
,则应确定一个值(例如,
-1
),以表示错误。此外,使用
无符号
比使用
更好(更准确):

int a=binom(n - 1, k - 1),b=binom(n - 1, k);
if (a<0 || b<0 || (unsigned)a+(unsigned)b>INT_MAX) return -1;
return a+b;
inta=binom(n-1,k-1),b=binom(n-1,k);

如果(aSigned overflow)是未定义的行为,则必须在溢出发生之前检查溢出

int a, b;
int c;

...

/* Compute a + b and store the result in c */

if (a > 0) {
    if (b > INT_MAX - a) {
        // a + b overflows (i.e., would be > INT_MAX)
    }
} else if (b < INT_MIN - a) {
        // a + b overflows (i.e., would be < INT_MIN)
}

c = a + b;
在您的示例中,还必须检查
n
k
不是
==INT\u MIN
,否则
-1
操作也将溢出。

一些建议:

1) 您使用的是有符号整数;如果使用的是严格的正数,则可能应该使用无符号int或无符号long。对于有符号整数,当发生算术溢出时,它将溢出到可能的最大负数

2) 编译器将沿INT_MAX行定义一个预处理器符号;你或许可以好好利用它,例如:

#inlcude <stdtypes.h>

uint32_t binom( uint32_t n, uint32_t k ){
  // (...)
  } else {
    int32_t   A = binom( n-1, k-1 )
            , B = binom( n-1, k );
    if( (double)A + (double)B > INT_MAX ){
      // error condition
    } else {
      retval = A+B;
    }
  }

  return retval;
}
#包括
uint32\u t binom(uint32\u t n,uint32\u t k){
// (...)
}否则{
int32_t A=binom(n-1,k-1)
,B=binom(n-1,k);
如果((双)A+(双)B>INT_MAX){
//错误条件
}否则{
retval=A+B;
}
}
返回返回;
}

另一个递归调用也应该有类型转换
(long)binom(n-1,k)
这假设
sizeof(long)>sizeof(int)
,但这不能保证为真。@fredrarson你是对的。补充说明@noMad,
long
int
的总和是
long
@aselr不一定有更广泛的本机类型可用(想想那些
int
long
都是64位的系统)。@从这里我没有想到这一点。。。希望现在我是正确的:)非常感谢——这是我使用的实现。我还有一个问题。如果出现溢出,我将如何中断函数?如果我返回一个像-1这样的整数标志(如下所示),由于这是递归的,它将继续求和,因为-1是一个数字。
a = binom(n - 1, k - 1);
b = binom(n - 1, k);

// if no overflow
c = a + b;

return c;
#inlcude <stdtypes.h>

uint32_t binom( uint32_t n, uint32_t k ){
  // (...)
  } else {
    int32_t   A = binom( n-1, k-1 )
            , B = binom( n-1, k );
    if( (double)A + (double)B > INT_MAX ){
      // error condition
    } else {
      retval = A+B;
    }
  }

  return retval;
}