【问题标题】:How is the "static" keyword affecting the calculation?“静态”关键字如何影响计算?
【发布时间】:2019-10-11 01:59:56
【问题描述】:

我在这段代码中有一个问题,使用 static 关键字。在这里,在n = 3之后,我以为r的值会是5,但我发现r的值是50!我不知道static 在这里是如何工作的:

int magic(int n)
{
    static int r = 5;
    if (n <= 0) return 10;

    if (n > 3)
    {
        r = 50;
        return(r + magic(n-1));
    }
    return(r - magic(n-1));
}

int main()
{
    int x;
    x = magic(8);
    printf("%d",x);
}

这里的输出是 290,因为 r 在所有情况下的值都是 50。请有人可以帮助我。

【问题讨论】:

标签: c recursion static


【解决方案1】:

当您有语句 static int r = 5; 时,这会向编译器发出信号:变量 r 将在编译时初始化为值 5 .这意味着,每次调用该函数时,它不会重置为5

另外,if (r &gt; 3) 行没有按照您的建议工作(请参阅我在您的问题中的评论)!改成if (n &gt; 3) 照你说的做。

不管怎样,下面的代码做了一些不同的事情(输出 245),但我不确定你期望的输出是什么:

#include <stdio.h>

int magic(int n)
{
    int r = 5; // NOT STATIC - so this is reset to 5 at the start of each call!
    if (n <= 0) return 10;
    else if (n > 3) { // Your "if (r > 3)" means the block will ALWAYS execute!
        r = 50;
        return(r + magic(n - 1));
    }
    return(r - magic(n - 1));
}

编辑:我将尝试添加一些说明!考虑在“全局”范围内(即不在任何函数内,甚至不在 main 内)声明和初始化静态变量的语句:

static int StatInt1 = 42;

当编译器遇到此语句时,它会为程序“分配”一部分内存,大到足以容纳int,并为该内存块分配代表42 的值。编译器生成任何机器代码指令来将给定的值移动到该内存中;事实上,它不可能生成这样的代码 - 因为没有运行该代码的“上下文”。

但是,如果您稍后(在某个函数中,或在 main 中)有这样的语句:

StatInt1 = 9;

然后编译器生成代码,将值9 的表示移动到先前为变量“分配”的内存中。这段代码的具体内容取决于编译器和目标机器,但假设它是一条指令MOVE 9 TO @StatInt1(其中@StatInt1 是“已分配”内存块的地址)。

现在,如果您要将static int StatInt1 = 42; 语句移动到函数体中(就像您所做的那样),这(根据定义)不会改变编译器解释语句的方式!它所做的只是访问该函数的变量“本地”。 仍然没有生成代码来将值移动到变量中!

但函数中声明为静态的变量的处理方式却大不相同——我们有时将此类变量称为“自动”!此类变量的内存块仅在实际调用函数时才“分配”,然后每次调用该函数时都会为其分配初始化程序中给定的值。 (通常,大多数编译器会在堆栈上创建内存:函数结束时“清除”的短期内存。)

在您的代码中,static int r = 5; 不会生成任何代码,因此在调用函数时不会“自动”重新分配值 5。因此,一旦以将值 50 分配给 r 的方式调用该函数,它将保持该值,直到您明确给它另一个值。

如果这是漫无边际的,我深表歉意 - 但我希望它能让你清楚(呃)发生了什么!

【讨论】:

  • 是的,你对“if (n>3)”是正确的,这是一个打字错误。我知道如果我们不使用“静态”,那么我们会得到输出 245。但是我很困惑当我们使用静态时我们如何得到输出 290。在最后一种情况下,当 (n
  • 因为变量被声明为static,它将保留它分配的任何值,直到它被赋予另一个值。但是,如果将 initialisation 中分配的值声明为 static,则它不会算作这些“直到”情况之一 - 它只会 被初始化一次(在编译时)。因此,使用您的代码,一旦 if 块被执行一次,该值将保持不变 - 当然,除非您添加一个 else 块并将其重置为“原始”值。
  • @AkshatJain 如果你考虑一下如果你有 static int r = 5; outside 任何函数(即作为全局变量)会发生什么,可能会更清楚!这将产生几乎相同的效果 - 除了您可以从任何地方(不仅仅是函数内部)“看到”变量。这有帮助吗?
  • 非常感谢阿德里安的解释!!!现在我明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多