下面是n
以下自然数和的递归函数。
int calculateSum(int n) {
if (n == 0){
return 0;
}else{
return n + calculateSum(--n); //Replacing --n with n-1 works
}
}
输入:5
如果I使用--n
,则输出为10;但如果I用n - 1
替换--n
,则返回正确的结果(15(。为什么有区别?
尽管这可能令人惊讶,但表达式的行为
n + calculateSum(--n);
是未定义,因为--n
不仅在递减1后计算为n
的值,还将n
更改为新值。然而,相对于左侧n
的其他评估(值计算(,该变化(副作用(是未排序。根据C11附录J.2.,当
标量对象上的副作用相对于同一标量对象上不同的副作用或使用同一标量物体的值进行的值计算是不排序的(6.5(。
这个问题中有更多同类错误。
当你得到一个错误的值时,你可以认为自己很幸运,因为你的编译器也可以生成返回"正确值">的代码。。。给定月相、优化设置或调用函数中的行数。。。
--n
还修改局部变量n
;表达式n-1
只是返回递减的值以将其传递给递归调用,但不修改输入参数。
关于输入5
:的第一次迭代的详细信息
- 正确为
return 5 + calculateSum(5-1);
- 使用
--n
时,您也会从n
递减,最终使用4 + calculateSum(4)
@user3386109&Yunnosch是这样表述的:使用--n
计算总和0...(5-1)
,而不是0...5
。
看到@Antti的回答,它解释说这实际上是未定义的行为。
下面的代码片段(一个函数(,你可以在主函数中调用它,它将递归地返回n个自然数的总和
int NNumbers(int n)
{
if(n != 0)
return n + NNumbers(n-1);
else
return n;
}
在你的代码中,你正在递减n的值,然后你正在计算和(即预递减(,因为输入是5,它在每次迭代中递减1,然后它将进行自然数的加法。所以你得到的结果是10而不是15
希望这对你有所帮助:(
谢谢