为什么我在这里得到分段错误?

时间:2017-08-01 00:23:33

标签: c recursion

我应该递归地打印两个数字的产品。 这是我的代码:

    #include<stdio.h>
int prod(int num1,int num2)
{
    if(num2=0)
    return num1;
    prod(num1+num1,num2-1);
}
int main()
{
    int n1,n2;
    printf("Enter two numbers to find their product:\n");
    scanf("%d" ,&n1);
    scanf("%d" ,&n2);
    printf("Product of %d and %d is %d",n1,n2,prod(n1,n2));
    return 0;
}

这是一个简单的代码,但为什么我会出现分段错误? 请帮忙。

6 个答案:

答案 0 :(得分:2)

2个问题:

- 您需要比较,而不是分配运算符。

- 您需要返回递归调用。

int prod(int num1,int num2)
{
    if(num2 == 0)
        return num1;
    return prod(num1+num1,num2-1);
}

答案 1 :(得分:1)

你有两个问题。比较值时需要==,并且需要返回递归表达式。至于这个程序的逻辑,我不相信你会实现产品?

#include<stdio.h>
int prod(int num1,int num2){
    if(num2==0){
        return num1;
    }
    return prod(num1+num1,num2-1);
}
int main(){
    int n1,n2;
    printf("Enter two numbers to find their product:\n");
    scanf("%d" ,&n1);
    scanf("%d" ,&n2);
    printf("Product of %d and %d is %d",n1,n2,prod(n1,n2));
    return 0;
}

答案 2 :(得分:1)

立即回答:您已经溢出堆栈,例如:你太复杂了#34;太远&#34;。每个函数调用占用调用堆栈上的一些额外空间,最终耗尽。

这引出了我们的问题:
为什么你的代码溢出堆栈?一般来说,这只是一个相当深的递归的问题,所以像你的例子一样简单的事情不应该冒任何风险(对于小数字)。

然而,密切关注你会发现你实际上无限期地递归 ,因为你已经将赋值运算符(num2 = 0)与比较运算符混淆了( num2 == 0)。
在C中,赋值运算符求值为赋值的值,因此num2 = 0的值为0。因此,您的条件if (num2 = 0)永远不会实现,您无休止地致电prod

要解决此问题,只需使用正确的运算符 - if (num2 == 0)代替if (num2 = 0)。另外,请记住,您可能希望返回递归调用的结果,否则您无需进行任何操作(例如return prod(num1+num1,num2-1))。

PS:如果num2恰好是否定的,会发生什么? PPS:缩进是你的朋友!

答案 3 :(得分:1)

@ Miket25您发布的代码实际上并不起作用。如果你需要一个完整的工作代码来计算正确的乘法(在num1和num2 = 0的情况下),这里是:

{% set domid='msg' ~ loop.index %}

答案 4 :(得分:0)

首先要理解的是,流程在给定的address space中运行。简单来说,地址空间是流程的足迹。地址空间的两个部分(以及其他部分)是堆和堆栈。虽然依赖于实现,但通常堆栈部分从高地址开始并占用空间(增长)到较低地址。另一方面,堆通常从较低地址开始并且增长到较高地址。请参考下图。

--------------  <- high address, say 24000
|   Stack    | grows downwards when a function is called and shrinks upwards when a function returns
--------------
|            |
|            |
|            |
|            |
|            |
--------------
|    Heap    | grows upwards when memory is allocated dynamically
--------------
| Text & Data| not entirely relevant in this case
-------------- <- low address, say 2000

每当调用函数时,堆栈部分向下增长。你为什么问?那是因为必须为activation record分配空间。简而言之,激活记录是一个空间块,它包含call stack上函数的参数和局部变量(以及返回地址)。

  

为什么我会在这里遇到分段错误?

现在,回到你的代码。您在此处执行的操作if(num2=0)是您将0分配给num2,分配表达式会导致0。因此,您的条件始终为false。因此,return语句永远不会执行,您继续调用prod函数。堆栈部分继续向下增长,直到达到限制时堆栈不再增长,并且您尝试写入堆栈不应访问的内存。这导致segmentation fault。这种现象被称为溢出堆栈。

使用==运算符检查数字(不是floatdouble)是否与另一个相等。这样做:if (num2 == 0)。这将导致您的return语句被执行(考虑到您没有首先传递负值),并且在您点击base case后堆栈帧将缩小。从而防止出现堆栈溢出的情况。

答案 5 :(得分:0)

我在其他答案中看到的所有代码都存在问题。

  • 所有人都不会照看操作数的标志。
  • 有些人没有输出正确的结果。
  • 有些人不会处理0值操作数。
  • 一个人在prod()函数中使用了一些静态变量而没有在函数start处初始化它们,因此函数prod()在同一次运行中不能再执行多次。

我解决了这个问题。

这里是代码:

#include <stdio.h>

#define abs(n) ( ((n)<0)?-(n):(n) )
#define sgn(n) ( ((n)<0)?-1:1 )

int prod(int num1,int num2)
{
    int s=sgn(num2),res;
    // printf("==> %d %d\n",num1,num2);

    if (!num1 || !num2)
        return 0;

    if(num2==s) {
        res=(s==-1)?-num1:num1;
        // printf("0u %d\n",res);
    } else {
        // printf("0n %d\n",num1);
        //res=(prod(num1,num2-s));
        res=(s==-1)?-num1:num1;
        res=(res+prod(num1,num2-s));
        // printf("1n %d\n",res);
    }

    return res;
}

int main(){
    int n1,n2,p;

    puts("The program terminate when the product results 0");
    do {
        printf("Enter two numbers to find their product:\n");
        scanf("%d" ,&n1);
        scanf("%d" ,&n2);

        p=prod(n1,n2);
        printf("Product of %d and %d is %d\n\n",n1,n2,p);
    } while(p);

    return 0;
}