繁体   English   中英

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

[英]why am i getting segmentation fault in this?

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

    #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;
}

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

两个问题:

  • 您需要比较,而不是赋值运算符。
  • 您需要返回递归调用。

见下文:

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

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

#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;
}

直接的答案:你正在溢出堆栈,例如你正在递归“太远”。 每个函数调用都会占用调用堆栈上的一些额外空间,最终你会用完。

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

但是,如果仔细观察,您会发现实际上是在无限递归,因为您混淆了赋值运算符 ( 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:缩进是你的朋友!

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

#include<stdio.h>

int prod(int num1,int num2)  
{
    static int num_old =0;
    static int i=0;
    static int somma =0;

    if (num2==0||num1==0) {

        return(num1*num2);

    } else {

        if(num2==1)
            return somma;

        if(i==0)
            num_old =num1;

        i++;
        somma = num1+num_old;
        prod(somma,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;
}

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

--------------  <- 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

每当调用函数时,堆栈部分都会向下增长。 你为什么问? 那是因为必须为激活记录分配空间。 简单来说,激活记录是一个空间块,它在调用栈上打包了一个函数的参数和局部变量(以及返回地址)。

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

现在,回到您的代码。 你在这里做什么if(num2=0)是你将0分配给num2并且赋值表达式导致0 因此,你的条件总是错误的。 结果return语句永远不会执行,您继续调用prod函数。 堆栈部分不断向下增长,直到达到极限,此时堆栈无法进一步增长并且您尝试写入堆栈不应该访问的内存。 这会导致分段错误 这种现象称为堆栈溢出。

使用==运算符检查数字(不是floatdouble )是否等于另一个数字。 这样做: if (num2 == 0) 这将导致您的return语句被执行(考虑到您首先没有传递负值)并且堆栈框架将在您遇到此基本情况后收缩。 从而防止溢出堆栈的情况。

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

  • 所有人都不关心操作数的符号。
  • 有些不输出正确的结果。
  • 有些不关心 0 值操作数。
  • 人们在prod()函数中使用了一些静态变量,而没有在函数开始时对它们进行初始化,因此函数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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM