C静态范围语义

nrm*_*mad 1 c

我正在学习C并且遇到了这个程序.

#include <stdio.h>
int a, b, c = 0;
void prtFun (void);
int main ()
{
    static int a = 1; /* line 1 */
    prtFun();
    a += 1;
    prtFun();
    printf ( "n %d %d " , a, b) ;
}

void prtFun (void)
{
    static int a = 2; /* line 2 */
    int b = 1;
    a += ++b;
    printf (" n %d %d " , a, b);
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

4 2
6 2
2 0
Run Code Online (Sandbox Code Playgroud)

它给出了以下解释

"'a'和'b'是全局变量.prtFun()也有'a'和'b'作为局部变量.局部变量隐藏全局变量(参见C中的Scope规则).当第一次调用prtFun()时,本地'b'变为2,本地'a'变为4.当第二次调用prtFun()时,使用相同的局部静态'a'实例,并创建'b'的新实例,因为'a'是static和'b'是非静态的.所以'b'再次变为2而'a'变为6. main()也有自己的本地静态变量名为'a',它隐藏了main中的全局'a'. main()中的()语句访问本地'a'并打印其值.相同的printf()语句访问全局'b',因为main中没有名为'b'的局部变量.此外,static的defaut值并且全局int变量为0.这就是为什么main()中的printf语句将0打印为b的值."

我的印象是C中的静态变量只声明一次并具有全局范围,并且所有全局变量都是隐式静态的.那么,考虑到全局变量的隐式声明或main中的显式声明的全局范围,您可以在不同的范围内重新声明这些静态变量,这是正确的吗?如果内存中只有一个地方用于静态变量并且它具有全局范围,那么该程序中具有相同名称的块特定静态变量是如何阻塞的?

谢谢

vva*_*hev 5

我会尽量简洁地帮助你.以下陈述在C 中根本正确:

  • "所有全局变量都是隐式静态的"
  • "内存中只有一个地方可用于静态变量"

全局变量可以是静态的或非静态的(常规的).不同之处在于,常规全局变量可以被其他翻译单元(简称C文件)使用,而静态变量则不能.

让我给你举个例子.假设你有两个C文件,ac和bc In ac:

int my_global_var;
static int a_static_var;
Run Code Online (Sandbox Code Playgroud)

在bc:

extern int my_global_var;
static int a_static_var;

int main() { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

您可以使用这两种方式构建程序,这样[假设您使用的是Linux]:

gcc -c a.c
gcc -c b.c
gcc -o prog a.o b.o
Run Code Online (Sandbox Code Playgroud)

现在,变量my_global_var相同的两个文件,但它实例化a.o翻译单元(BC认为这是一个EXTERN变量).虽然变量a_static_var不是唯一的.每个翻译单元都有自己的a_static_var变量:它们完全不相关.

回到您的示例,静态变量也可以具有函数范围:在这种情况下,在不同函数内定义的静态变量是完全不相关的,与单独的转换单元内的全局静态变量不相关的方式相同.在您的情况下,您可以考虑两个静态a变量AS如果它们被调用__main_a__prtFun_b.当你编译程序时,这实际上非常接近引擎盖下发生的事情.

现在,为了完成图片,有一条规则允许您定义本地(静态或非静态)变量,即使这将隐藏使用相同名称定义的全局变量.因此,prtFun()例如,当您访问时b,您正在访问本地非静态变量,当您访问时a,您正在访问本地静态a变量.同样如此main().在任何情况下,您的代码都不会触及全局a, b, c变量.

我希望我一直很有帮助.