【问题标题】:Static variables local to function局部于函数的静态变量
【发布时间】:2013-09-29 14:27:41
【问题描述】:

我正在学习 C 中的存储类。我有一个简单的代码

enter code here
int f1()
{
    static int i=0;
    i++;
    printf("%d",i);
}

int f2()
{
    printf("%d",i);
}

int main()
{
    f1();f2();f1();f2();
}

编译器给出错误,因为在 f2() 中未声明“i”。 正如我所想,内存静态变量分配在程序内存的数据部分中。因此该文件中的任何函数都应该能够访问它。

编译器如何知道函数中本地声明的变量仅绑定到该函数?编译器如何评估它?

【问题讨论】:

标签: c memory memory-management compiler-errors static-variables


【解决方案1】:

静态变量确实存储在数据部分,但仅在声明它们的函数范围内。

你应该做以下事情

static int i=0;
int f1()
{
    i++;
    printf("%d",i);
}

int f2()
{
    printf("%d",i);
}

现在两个函数都可以访问变量 i。

【讨论】:

    【解决方案2】:

    尽管static 变量的生命周期与定义它的范围无关(与具有自动存储持续时间的变量不同):

    {
        static int i=0;
        i++;
        ...
        {
            i++;  // <-- still well defined, even in nested scope
        }
    }
    i++;  // <-- undefined
    

    它只能在这个范围内访问。编译器只是检查符号 i 之前是否已定义,它会看到 i 尚未在该范围内定义(static int i=0; 定义了一个可在本地访问的变量~编译器不关心它的生命周期)。

    如果您需要在其范围之外对其进行访问,则必须通过引用(其地址)将其传递出去或使其成为全局对象:

    static int i = 0;
    ...
    {
        i++;
    }
    ...
    i++;  // <-- accessing global variable
    

    【讨论】:

    • 是的,通过将其设为全局或传递引用,我肯定可以在任何地方访问它。但是在静态分配的情况下,编译器如何考虑与特定函数相关的特定变量?
    【解决方案3】:

    永远记住范围是编译时而不是运行时。 C 有一个扁平的内存结构。这意味着您可以从任何地方访问任何内容。您可以制作 i 的指针并可以访问它。但是,当变量的范围结束时,C 会说未定义的行为。这完全是一个编译器限制。您还可以查看链接 - Is scope in C related only to compile time, as we know we can access any memory at run time? 了解更多详情。此外,这可能会有所帮助A static variable and a global variable both reside in data segment. Still, static variable has scope limited. Why?。所以,是翻译单元给你带来了错误。

    让我们通过例子来理解这一点。

    #include "stdio.h"
    
    
    int *ptr_i;
    
    void func1()
    {
      static int i = 0;
    
      ptr_i = &i;
    
      i++;
      printf("The static i=%d\r\n",i);
    
    }
    
    int main(int argc, char *argv[])
    {
    
      func1();
    
      (*ptr_i)++;
    
      func1();
    
    
    }
    

    这个程序的输出如下。 静态 i=1 静态 i=3

    正如您所理解的,范围不是运行时。我能够通过指针访问 i 使用的内存位置。因此,您可以访问 C 中的任何内存,因为它是一个平面内存结构。在这个例子中,我使用指向 i 的指针访问了 i 的内存。注意,编译器永远不会抛出任何错误。因此,范围是编译时而不是运行时。

    【讨论】:

    • 如果是,范围的具体用途是什么?为什么制定这个标准?你能举个例子解释一下它的用途吗?
    • 我的答案已经修改,请查看
    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    相关资源
    最近更新 更多