关于C#:函数本地的静态变量

Static variables local to function

我在C学习存储课程,我有一个简单的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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"。正如我所想,内存静态变量被分配到程序内存的数据部分,所以该文件中的任何函数都应该能够访问它。

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


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

1
2
3
4
5
6
7
8
9
{
    static int i=0;
    i++;
    ...
    {
        i++;  // <-- still well defined, even in nested scope
    }
}
i++;  // <-- undefined

它只能在此范围内访问。编译器只是检查符号i以前是否定义过,并且发现i没有在该范围内定义(static int i=0;定义了一个可在本地访问的变量~编译器不关心它的生存期)。

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

1
2
3
4
5
6
7
static int i = 0;
...
{
    i++;
}
...
i++;  // <-- accessing global variable


请始终记住,作用域是编译时而不是运行时。C具有平面内存结构。这意味着你可以从任何地方访问任何东西。你可以给我做一个指针,然后访问它。但是,c表示当变量的作用域结束时,未定义的行为。这完全是一个编译器限制。您还可以看到链接——C中的作用域只与编译时相关,因为我们知道在运行时可以访问任何内存?了解更多详细信息。此外,静态变量和全局变量都位于数据段中,这可能会有所帮助。不过,静态变量的作用域有限。为什么?所以,是翻译单元把错误抛给了你。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include"stdio.h"


int *ptr_i;

void func1()
{
  static int i = 0;

  ptr_i = &i;

  i++;
  printf("The static i=%d

"
,i);

}

int main(int argc, char *argv[])
{

  func1();

  (*ptr_i)++;

  func1();


}

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

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


静态变量确实存储在数据段中,但只在声明它们的函数范围内。

你应该做以下的事情

1
2
3
4
5
6
7
8
9
10
11
static int i=0;
int f1()
{
    i++;
    printf("%d",i);
}

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

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