让我们从这个函数开始:
int sum_of_numbers(int n1){
int sum;
if(n1 <= 25){
printf("%d ", n1);
sum = n1 + sum_of_numbers(++n1);
}
else
return 0;
}
暂时忽略这是一个递归函数的事实。事实上,让我们将递归调用替换为非递归调用:
int sum_of_numbers(int n1){
int sum;
if(n1 <= 25){
printf("%d ", n1);
sum = n1 + some_other_mystery_function(++n1);
}
else
return 0;
}
根据经验,当您第一次学习递归时,假设递归调用是针对不同的函数通常会有所帮助。递归中的许多错误实际上是函数调用和返回中更简单的错误,因为您过于关注递归位而被忽略了。
进行了更改后 - 您是否注意到此功能有什么不寻常之处?具体来说,如果您传入小于或等于 25 的值 n1,将返回什么值?在这种情况下,函数到达结束时不会返回任何内容。具体来说,我们输入if 语句,执行printf,调用some_other_mystery_function,然后退出函数的末尾,没有返回任何内容。在 C 中,这是未定义的行为,返回的值基本上取决于编译器、操作系统和行星的对齐方式。
这导致了通用的可转移技能 1:确保在编写递归函数时,始终返回一个值。大多数函数都是如此,尤其是在递归的情况下。
这里还有其他一些可疑之处。请注意,您将sum 变量设置为某个值,但sum 是一个局部变量,以后在函数中永远不会引用它。这应该会引发一些警钟 - 为什么我们设置一个局部变量而不读取它?
我认为你的意思更像是这样的:
int sum_of_numbers(int n1){
if(n1 <= 25){
printf("%d ", n1);
return n1 + some_other_mystery_function(++n1);
}
else
return 0;
}
这总是返回一个值,并且永远不会写入未读取的局部变量。
不过,这里还有另一个问题。看这一行:
return n1 + some_other_mystery_function(++n1);
在这里,您在表达式中的某个位置读取n1,并在另一个位置写入++n1。这是一件坏事,因为没有办法保证n1 的第一次使用评估为“n1 在评估++n1 之前的值”还是“n1 之后的新值”我们做了++n1。”再一次,注意这个语句是一个return 语句,所以在这行执行之后,就再也没有机会再次接触n1。我想你的意思是这样的?
return n1 + some_other_mystery_function(n1 + 1);
这更清楚地意味着“将n1 + 1 作为参数传递给函数。”
这导致通用的、可转移的技能 2:避免使用 ++、+=、-= 等作为函数的参数。在某些情况下,这将正常工作,但在许多情况下,它会引入错误。而是传递value + 1、value + 137、value - 271 等。
最后,可转移技能 3 - 编译器可以警告您所有这些问题。如今,大多数编译器在您提高警告设置时,会警告您写入未读取的局部变量,或者在函数末尾不返回任何内容,或者增加表达式中其他地方使用的变量。我建议启用这些设置,因为这可能会提示您这里有些地方不太对劲。您可能不了解警告的全部内容,这很好!如果发生这种情况,请随时在网站上的单独问题中发布您的代码和警告消息,其他人可以查看它。