我asked前几天
#include <stdio.h>
int MyAdd(int);
main ()
{
int i;
int c = 0;
c = MyAdd(5);
printf("%d\n", c);
}
int MyAdd(int a)
{
if(a > 0)
return a + MyAdd(--a);
else
return 0;
}
为什么这个结果是10而不是15,我得到了答案
当在表达式中使用时,副作用操作符会做出有趣的,意想不到的事情,因为你基本上受编译器的支配。
在这种情况下,您的编译器在第一个运算符之前评估+ MyAdd( - a)的第二个运算符。所以,在添加变量之前,你要减少变量。
理解它!我正在玩我的代码,我用--i
替换i--
,我的编译器没有得到任何错误,当我运行它时我得到了Segmentation fault (core dumped)
我想知道为什么发生了这件事。
答案 0 :(得分:2)
“我遇到了分段错误(核心转储)”
在这段代码中,您会看到每次调用MyAdd函数时,都会向它传递一个较小的参数(因为--a):
#include <stdio.h>
int MyAdd(int);
main ()
{
int i;
int c = 0;
c = MyAdd(5);
printf("result: %d\n", c);
}
int MyAdd(int a)
{
int res = 0;
if(a > 0) {
res += a + MyAdd(--a);
printf("%d\n", res);
return res;
}
else
return 0;
}
输出:
0 // you pass 1 to your function and decrement the argument
1 // you pass 2
3 // you pass 3
6 // you pass 4
10 // you pass 5. Because you decrement the argument each time
// you pass it to your function, this will return normal result.
result: 10
但如果您将--a
更改为a--
,则始终会将5
传递给MyAdd
。
这将是无限循环,因为:(5 + (5 + (5 + (5 + ...
。如你所见,5
总是超过0
,所以如果总是递归调用MyAdd
函数...
所以返回值会增加并增加,直到发生溢出:
ISO C99标准规定整数溢出会导致“未定义” 行为“,意味着符合标准的编译器可以这样做 他们喜欢的任何东西都完全忽略了溢出到流产 该程序。大多数编译器似乎忽略了溢出,导致 存储意外或错误的结果。
“为什么这个结果是10而不是15”
当您第一次致电MyAdd
时,最好考虑传递给您的功能的参数。 然后你会得到15而不是10 :
#include <stdio.h>
int MyAdd(int);
main ()
{
int i;
int c = 0;
c = MyAdd(5);
printf("result: %d\n", c);
}
int MyAdd(int a)
{
int res = a; // here it is
if(a > 0) {
res += MyAdd(--a);
printf("%d\n", res);
return res;
}
else
return 0;
}
答案 1 :(得分:1)
在执行函数调用之前, 要执行递减部分。如果你不这样做,你得到的只是(5 +(5 +(5 +(5 +(5 + ...),最终是堆栈溢出和随后的段错误。
答案 2 :(得分:1)
它是一个递归函数,只有当它返回到调用函数时才会发生递减。在这种情况下i--
。因此i
将始终为&gt; 5。
答案 3 :(得分:1)
坚持 - 之前变量递减值并返回它(因此你的函数每次传递得到一个较小的参数)。
坚持 - 之后变量返回当前值,然后递减(因此你的函数重复地将相同的值传递给它自己:值不会减少,直到调用返回为止,它不会因为它递归地出现同样的问题而获胜。
最后,你用自己的函数调用填充堆栈,程序崩溃(堆栈是程序知道的位置&#34;返回&#34;:它每次都将返回地址添加到堆栈中你输入一个函数,并在每次我们回来时删除地址。我们永远不会回来,所以最终我们用完了空间。)