中止陷阱:6(计算长数阶乘)

Abort trap: 6 (Calculating a long number factorial)

我正在按照以下函数计算大数的阶乘 link,我想更多地了解为什么会发生某些事情...

#include<stdio.h>
#define MAX 10000
void factorialof(int);
void multiply(int);
int length = 0;
int fact[MAX];

int main(){
    int num;
    int i;

    printf("Enter any integer number : ");
    scanf("%d",&num);
   
    fact[0]=1;

    factorialof(num);
   
    printf("Factorial is : ");
    for(i=length;i>=0;i--){
         printf("%d",fact[i]);
    }
    return 0;
}

void factorialof(int num){
    int i;
    for(i=2;i<=num;i++){
         multiply(i);
    }
}
void multiply(int num){
    long i,r=0;
    int arr[MAX];
    for(i=0;i<=length;i++){
                arr[i]=fact[i];
        }

    for(i=0;i<=length;i++){
         fact[i] = (arr[i]*num + r)%10;
         r = (arr[i]*num + r)/10;
         //printf("%d ",r);
    }
    if(r!=0){
         while(r!=0){
             fact[i]=r%10;
             r= r/10;
             i++;
         }
    }
    length = i-1;   
}

我的问题是:

  1. MAX常量的真正含义是什么?更大或更小是什么意思?
  2. 我发现如果我有一个 MAX = 10000(如示例中所示),我最多可以计算 3250!如果我尝试使用 3251!我收到 'Abort trap: 6' 消息。为什么是这个数字?它来自哪里?
  3. 如果我使用标志 -m32 为 32 位机器编译这段代码会有什么不同? 运行 他会和 64 位的一样吗?

谢谢!

  1. MAX为factarr中的元素个数;尝试访问索引 >= MAX 的元素是错误的。
  2. 错误消息通常特定于您正在使用的环境,您没有提供详细信息。
  3. 它们并不相同,但差异(例如,指针的大小)不应以任何可识别的方式影响此代码。

正如 Scott Hunter 指出的那样,MAXfactarr 数组中元素的最大数量,这意味着它是可以出现在程序用完 space.

之前的结果

请注意,代码仅在其数组声明中使用 MAX。它没有在任何地方使用 MAX 来确定它是否正在尝试读取或写入超出这些数组末尾的内存。这是一件坏事™。您的 "Abort trap: 6" 错误几乎肯定会发生,因为试图计算 3251!正在这样做:使用 arrfact.

的过大索引

要查看给定阶乘所需的位数,您可以增加 MAX(例如,增加到 20,000)并将 main 中现有的 printf 调用替换为类似这个:

printf("Factorial requires %d digits.\n", length + 1);

请注意,我使用 length + 1 是因为 length 本身并不是位数:相反,它是 fact 中包含最多的数组位置的索引-结果的有效数字。如果我尝试计算 3251!,输出为:

Factorial requires 10008 digits.

这比您在 fact 中的可用数字多了八位,默认 MAX 值为 10,000。一旦程序逻辑超出数组中分配的space,它的行为是不确定的。您碰巧看到错误 "Abort trap: 6."

有趣的是,这是我尝试计算 3250 时的输出!:

Factorial requires 10005 digits.

MAX 设置为 10,000 时,程序仍无法可靠地运行,所以您的程序计算出 3250 的事实!成功可能令人惊讶,但这就是未定义行为的本质:也许你的程序会产生正确的结果,也许它会崩溃,也许它会变得有自我意识并向俄罗斯的目标发射导弹 (because it knows that the Russian counterattack will eliminate its enemies over here) .像这样编码不是一个好主意。如果您的程序需要的 space 多于可用的数量以完成计算,它应该停止并显示适当的错误消息,而不是试图继续它正在做的事情。