【问题标题】:How do local static variables work in method?局部静态变量如何在方法中工作?
【发布时间】:2020-08-26 14:02:28
【问题描述】:

下面是我的代码:

//main.c

int f()
{
    static int x = 0;
    x += 1;
    return x;
}

int main()
{
   f();
   printf("%d", f());
}

输出为2

我知道静态变量会保持状态,但是由于我调用了两次f(),每次x首先设置为0(static int x = 0;),然后加1,那么输出应该是1不管我打了多少次f()

【问题讨论】:

  • 在回答之前:考虑一下这个问题已经有 8 个答案,而且这个话题相当基础。您的回答是否增加了一些新的内容或以显着的方式改进了已经说过的内容?

标签: c function static


【解决方案1】:

static 变量不仅持续存在,它们仅被初始化一次,因此x 不是“每次都先设置为 0”,它在第二次调用中保持 1 然后增加。确实如此

static int x = 0;  // x is initialized once only

很不一样
static int x;
x = 0; // x is set to 0 with every call

【讨论】:

    【解决方案2】:

    每次 x 设置为 0

    不,您正在错误地阅读代码。这里的= 并不表示赋值,而是表示初始化,因为它是声明的一部分。变量的初始值明确指定为 0。静态变量仅在程序执行期间初始化一次。如果它们的声明出现在函数中,则不会改变该行为。

    此外,静态变量的初始值设定项必须是常量表达式(可以在编译时计算为已知值的表达式)。这意味着实际上,实现不需要引入代码来在函数内部进行任何初始化。该值可以在程序启动时简单地加载到变量的存储中。

    【讨论】:

      【解决方案3】:

      您对f() 进行了两次调用,x 具有静态存储持续时间,它的生命周期是程序的整个执行过程。这就是打印 2 而不是 1 的原因。

      【讨论】:

        【解决方案4】:

        ...但是由于我两次调用f(),所以每次x 都设置为0 第一个(static int x = 0;,...”

        没有。每次调用 f 时,x 都未设置为 0

        static 变量仅在第一次调用定义它们的函数时初始化一次。

        automatic 变量相比的特殊之处在于分配的内存对象会一直持续到程序结束。

        x 的对象和值在对函数 f 的不同调用之间保持不变。因此,x 在每次调用该函数时都会递增 1,而不会重置为曾经初始化的值。

        // Calls to f() in order
        f();         // value of x at the end of the function: 1
        f();         // value of x at the end of the function: 2
        f();         // value of x at the end of the function: 3
        f();         // value of x at the end of the function: 4
        // and so on.
        

        所以,当你调用f() 两次时,2 是函数返回时x 的正确值。


        旁注:

        • 0 的显式初始化是多余的。 static 变量默认初始化为0

        • 不应省略 C 中函数的参数列表定义/声明。而不是int f(),写int f(void)int main() 也应编辑为 int main (void)int main() 已过时。

        【讨论】:

        • 使用int main(void) 表示法很好,但请注意C11 标准(§6.5.3.4 The sizeof and _Alignof operators 中的示例3)显示int main() { … }。当然,它不是规范性的,因为它是一个例子,但是……。
        • @JonathanLeffler 是的,我知道。我也发现了这些例子并想知道。我有一个关于这个案例的conversation with Keith,结论是更好地使用int main (void) 表格。因此建议。
        • 我 100% 同意“更好”。我在谈论“符合标准”。它是合规的代码,但没有超越现代实践。
        • @JonathanLeffler Keith 保证遵守未来标准的理由是什么(以防委员会消除这种歧义)?
        • 毫无疑问,使用显式int main(void) 形式更好——但目前,int main() 形式也符合标准,即使不是首选表示法。类似的 cmets 适用于函数定义的非原型风格。旧样式仍然符合标准;它根本不应该被使用。当您改写答案时(使用“已过时”),这涉及我的狡辩(这意味着小规模的狡辩,而不是如何编写良好的 C 代码哲学的主要练习),所以一切都很好,虽然我会使用“过时”而不是“过时”。
        【解决方案5】:

        静态变量也可以在局部范围内声明。 static duration 表示对象或变量在程序启动并在程序结束时释放。 (from here)

        所以这对您的示例程序意味着2 是正确的:

        以下示例代码加上顶部的语句说明了原因:

        初始调用:

        static int x = 0;  // unlike non-static variables, initialization is executed 
                           // only once on 1st call to function.
                           // Also unlike non-static, local variables, locally created static 
                           // variables are initialized to 0 automatically  
                           // making the explicit assignment to 0 unnecessary. 
                           // (although still a good habit. :)) 
        ...
        x++; //x==1
        

        第二次调用:

        static x = 0 //skipped 
        ...
        x++; //x==2
        

        第三次调用:

        static x = 0 //skipped 
        ...
        x++; //x==3
        

        以此类推,直到程序结束...

        (已将x += 1; 替换为其惯用的快捷语法:x++;

        【讨论】:

          猜你喜欢
          • 2011-11-02
          • 1970-01-01
          • 2021-08-10
          • 1970-01-01
          • 2012-05-25
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多