C语言递归阶乘疑问:为何用--n返回24?(--n)等于n-1吗?
为什么用
--n的阶乘函数返回24而不是120? 首先直接回答你的第一个疑问:--n和n-1完全不等价。虽然两者的表达式求值结果都是n减1后的数值,但--n带有一个关键的副作用——它会直接修改变量n本身的存储值;而n-1只是计算出一个临时的结果,不会改变原变量n的值。这就是你的代码出错的核心原因。
我们来拆解你的错误代码执行过程:
return n * factorial(--n);
在C语言中,乘法操作的两个操作数(这里的n和factorial(--n))的求值顺序是未指定的——编译器可以选择先计算左边的n,也可以先执行右边的--n再调用函数。在你的编译环境中,编译器选择了先执行--n:
- 第一次调用
factorial(5)时,先执行--n,把n的值从5改成4; - 然后计算左边的
n,此时n已经是4了; - 所以实际计算的是
4 * factorial(4); - 进入
factorial(4)后,重复同样的逻辑:先把n改成3,再计算3 * factorial(3); - 以此类推,最后得到的结果是
4*3*2*1=24,而非预期的5*4*3*2*1=120。
而当你改成return n * factorial(n-1);时,n-1不会修改原变量n的值:
- 不管编译器先计算左边的
n还是先调用factorial(n-1),左边的n始终是当前函数的原始参数值; - 右边调用的是
factorial传入n-1的临时值,完全不影响原n,所以计算逻辑是正确的阶乘递归。
另外补充一点:你提到知道不能用n--,这是对的——n--是后置递减,表达式的值是n的原值,但执行完表达式后n会被减1,不过在这个场景里,同样会因为修改n的值,导致和--n类似的求值顺序问题,同样不可取。
总结一下:在同一个表达式中,不要同时对同一个变量进行修改操作(比如--n、n++、n+=1等)和读取操作,这种写法会依赖编译器的求值顺序,导致结果不可预测,属于非常糟糕的编程习惯。
内容的提问来源于stack exchange,提问作者pickle323
相关产品推荐
相关产品推荐

