【问题标题】:What's the difference between --i and i - 1 in a parameter in C?C中参数中的--i和i - 1有什么区别?
【发布时间】:2019-11-17 08:16:53
【问题描述】:

我正在编写一个以递归方式打印出前 10 个自然数的程序。首先,我放了一个参数“--num”

int natural_numbers(int num) {
    if (num > 1) // Base case
        natural_numbers(--num);
    printf("%d ", num);
}
Input: 10
Output: 1 1 2 3 4 5 6 7 8 9

然后我将参数更改为“num - 1”,它会打印出我的预期。

int natural_numbers(int num) {
    if (num > 1) // Base case
        natural_numbers(num - 1);
    printf("%d ", num);
}
Input: 10
Output: 1 2 3 4 5 6 7 8 9 10

我不知道为什么第一个输出是错误的。我需要一些帮助。

【问题讨论】:

  • --numnum 减 1,然后在下一行打印该数字。
  • 这是C还是c++
  • 杰克,你之前没有接受过其中一个答案吗(@Bartek,如果我没记错的话)?是什么让您改变主意重新提出这个问题?

标签: c++ c recursion operators parameter-passing


【解决方案1】:

你认为我们会想通过 num 3 调用那个函数

当您使用 --num 时,就像您在 natural_function 中更改输入的数字一样

调用 natural_numbers(3) 时的本地堆栈如下所示

// =========call natural_number(3)

natural_number(2) // --num (change num itself. its like num = num - 1 then pass it)

// But here in this local stack  block "num" becomes 2 

print 2 // <== here it prints 2 on the backward step

// ========= call natural_number(2)

natural_number(1) // --num (change num itself. its like num = num - 1 then pass it)

// But here in this local stack  block "num" becomes 1

print 1 // <== Here it prints 1 on the backward step

// ========= call natural_number(1)

print 1 // Here we go out of stack by printing 1  

Result: 1 1 2

现在如果我们用 (num - 1) 调用该函数 这意味着您不想更改进入自己的本地堆栈块的“num”变量。

(num - 1) 的本地堆栈将是这样的:

// ========= call natural_number(3)

natural_number(2) // (num - 1) (num wont change. its like temp = num - 1 then pass temp to it)

print 3 // Here it prints 3 on the backward step

// ========= call natural_number(2)

natural_number(1) // (num - 1) (num wont change. its like temp = num - 1 then pass temp to it)

print 2 // <== Here it prints 2 on the backward step

// ========= call natural_number(1)

print 1 // Here we go out of stack by returning 1  

Result: 1 2 3

【讨论】:

    【解决方案2】:

    如果你想将num - 1 传递给一个函数(实际上你在这里所做的那样),方法就是简单地调用natural_numbers(num - 1)。没有什么花哨的需要。这不是巧合。

    C 的特殊 ++-- 运算符所做的更多——明显更多——不仅仅是加或减 1。它们加或减 1,并将递增或递减的变量存储回原始位置。所以--num 不只是从num 中减去1,它会将值num - 1 存储回num。但这不是你想要的。您不想修改num,因为在每次递归调用时,您都希望打印出您开始使用的num 的值,而不是您传递给递归的递减版本。

    【讨论】:

      【解决方案3】:

      num - 1 创建一个新的临时 int,作为 num 的副本,并从该临时 int 中减去 1。

      --numnum 本身减去 1。

      另外,请注意您的函数natural_numbers 应该是void。它现在显示int,但你没有返回任何东西,所以你的程序确实有Undefined Behaviour

      您可以使用调试器并单步执行您的程序以查看何时出现问题,或者添加一些调试打印。这是您的原始程序,在递归调用 beforeafter 之后打印。之前和之后的数字应该是相同的,这样算法才能工作,正如您将看到的那样,它们不是。

      #include <iostream>
      #include <string>
      
      void natural_numbers(int num) {
          static size_t indent = 0;
          std::cout << std::string(indent, ' ') << "num before: " << num << "\n";
          if(num > 1) { // Base case
              ++indent;
              natural_numbers(--num);
              --indent;
          }
          std::cout << std::string(indent, ' ') << "num after: " << num << "\n";
      }
      
      int main() {
          natural_numbers(10);
      }
      

      【讨论】:

      • 谢谢,我明白了,但是为什么它打印了两次数字 1 而缺少数字 10?
      • 由于在打印之前更改了 num,因此无法打印 10(如果 10 是您的原始输入数字)。 1 出于同样的原因打印。当 num==2 你改变 num 并调用 natural_numbers 这将打印 1,当调用返回时,你再次打印 1。
      【解决方案4】:

      在第一部分中,您使用预减 -- 运算符更改 num 值。您的第二个代码不会更改 num 值(它将临时 num - 1 值传递给函数调用)。

      所以如果你下一个 printf num 值它是不同的。在第一个代码部分它减一,在第二部分它是原始num 值。

      如果您最初使用num == 10 调用natural_numbers,您可以在下面跟踪其值如何在下一行更改/不更改。

                                        //      num (its value)
      int natural_numbers(int num) {    //       10
          if (num > 1) // Base case     //       10
              natural_numbers(--num);   //       10 / and 9 (after execution)
          printf("%d ", num);           //        9
      }
      
      int natural_numbers(int num) {    //       10
          if (num > 1) // Base case     //       10
              natural_numbers(num - 1); //       10
          printf("%d ", num);           //       10
      }
      
      

      【讨论】:

      • 哦,原来如此。非常感谢:))
      猜你喜欢
      • 1970-01-01
      • 2017-05-17
      • 2011-08-06
      • 2014-12-25
      • 1970-01-01
      • 2017-10-23
      • 2011-03-21
      • 2021-08-25
      相关资源
      最近更新 更多