【问题标题】:Does (--n) equal (n - 1)? [duplicate](--n) 是否等于 (n - 1)? [复制]
【发布时间】:2018-09-01 16:46:38
【问题描述】:

我最近开始尝试学习 C 并且正在做一个涉及创建递归阶乘函数的练习。 为什么下面会打印出 24 的答案?

#include <stdio.h>

int factorial(int n);

int main(void)
{
    int n = 5;
    printf("%d\n", factorial(n));
    return 0;
}


int factorial(int n)
{
    if (n <= 1)
        return 1;
    else
        return n * factorial(--n);
}

如果我将最后一行更改为

返回 n * 阶乘(n - 1);

我得到了预期的 120。

我知道您不能使用 n-- b/c 它只会在处理完行后减少 n 但 --n 有什么问题&为什么它给出 24?

【问题讨论】:

  • --n 更改变量 n,n-1 没有,在您的情况下使用 n-1
  • 这个程序导致未定义的行为,任何事情都可能发生
  • 如果您已经开始学习 C,那么还要注意,递归的使用应仅限于程序解决方案不存在的情况,或者过长或难以实施的情况。为什么?因为每个递归调用都是一个单独的函数调用,需要它自己的函数堆栈。对于factorial,这很好,但是如果您启动数万或数十万或更深的递归,您可能会迅速耗尽资源。谨慎使用它们。
  • @M.M - 您指的是“n 的值是多少?”在return n * factorial(--n);
  • 引用是C11 Standard - 6.5 Expressions(p2) "如果标量对象的副作用相对于同一标量对象的不同副作用或使用相同标量对象的值的值计算是无序的标量对象,行为未定义。”

标签: c decrement unary-operator


【解决方案1】:

--n 有什么问题 & 为什么它给出 24?

问题是--n修改了n,所以你的行

return n * factorial(--n);

可能评估如下:

return (n - 1) * factorial(n - 1);

因为 factorial(--n) 在表达式的第一项 n 之前被评估。另一方面,第一项可以在第二项之前进行评估,你会得到你期望的结果。或者,可能会发生完全不同的事情,因为(正如 M.M 和 David C. Rankin 在 cmets 中指出的那样)当您尝试使用变量并在同一表达式中修改它时会发生什么 is undefined

如果标量对象的副作用相对于同一标量对象的不同副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义。

让我们来解决你的标题问题:

(--n) 是否等于 (n - 1)?

--nn - 1 的值相同,但前者的表达式有修改n 的副作用。您真的应该将--n 视为表达式(n = n - 1) 的简写。

【讨论】:

  • 好答案 +1,但可能会添加一些文档以操作顺序描述此行为。我想知道 Java 是否会以同样的方式表现(它可能会)。
  • 其实是未定义的行为
  • @M.M 这就是我使用可能这个词的原因,但也许最好明确一点。将编辑。
  • 我在 Java 中测试了这段代码 ( n * factorial(--n) )。结果是 120。逻辑相同,但与 C 和 Java 不同。
  • @JunheeShin Java 显然有一条规则是subexpressions are evaluated from left to right。如果是这种情况,那么您可以通过颠倒条款来创建类似的情况:(factorial(--n) * n)
猜你喜欢
  • 2020-09-23
  • 1970-01-01
  • 2011-09-08
  • 1970-01-01
  • 2020-08-05
  • 2016-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多