C static scope semantics
我正在学习C,并且遇到了这个程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
输出如下:
1 2 3 | 4 2 6 2 2 0 |
它给出了以下解释
"'a'和'b'是全局变量。prtfun()还具有"a"和"b"作为局部变量。局部变量隐藏全局变量(参见C中的作用域规则)。当第一次调用prtfun()时,本地"b"变为2,本地"a"变为4。第二次调用prtfun()时,使用本地静态"a"的同一个实例,并创建"b"的新实例,因为"a"是静态的,"b"是非静态的。所以"b"再次变为2,"a"变为6。main()还具有自己的名为"a"的局部静态变量,该变量在main中隐藏全局"a"。main()中的printf()语句访问本地"a"并打印其值。printf()语句访问全局"b",因为main中没有名为"b"的局部变量。此外,静态和全局int变量的默认值为0。这就是为什么main()中的printf语句将0作为b的值打印出来的原因。"
我的印象是C中的静态变量只声明一次,具有全局范围,并且所有全局变量都是隐式静态的。那么,在给定全局变量隐式声明的全局范围或main中的显式声明的全局范围的情况下,如何正确地在不同的范围内重新声明这些静态变量呢?如果一个静态变量在内存中只有一个位置,并且它有一个全局范围,那么这个程序中如何有具有相同名称的块特定静态变量?
谢谢
我会尽可能简洁地帮助你。在C语言中,以下陈述是不正确的:
- "所有全局变量都是隐式静态的"
- "静态变量在内存中只有一个位置"
全局变量可以是静态的或非静态的(常规)。不同之处在于,常规全局变量可以被其他翻译单元(简而言之,C文件)使用,而静态变量则不能。
我给你举个例子。假设您有两个C文件,A.C和B.C。在公元前:
1 2 | int my_global_var; static int a_static_var; |
在公元前:
1 2 3 4 | extern int my_global_var; static int a_static_var; int main() { /* ... */ } |
您可以使用这两个C文件构建一个程序,这样[假设您使用的是Linux]:
1 2 3 | gcc -c a.c gcc -c b.c gcc -o prog a.o b.o |
现在,变量
回到您的示例,静态变量也可以有函数范围:在这种情况下,在不同函数中定义的静态变量是完全不相关的,这与单独翻译单元中的全局静态变量是不相关的。在你的例子中,你可以把两个静态的
现在,为了完成这幅图,有一个规则允许您定义本地(静态或非静态)变量,即使这将隐藏用相同名称定义的全局变量。因此,在
希望我能帮上忙。
尽管vvartchev已经提供了一个很好的解释,我还是想加上一两件事…
大多数书籍、教程等都使用静态的,如代码中所示,以在多个函数调用上保留局部变量的值。然而,这只是静电的一个用途,而且——在我看来——更无用的用途之一。
让我们重温一下这句话
Global variables can be static or non-static (regular). The difference is that regular global variables can be used by other translation units (briefly, C files), while the static variables cannot.
静态的这种用法没有在代码中演示,但实际上非常有用,因为它本质上意味着您可以定义变量(和函数!)它们是"私有的",并且从另一个C文件中永远看不到。这允许将哪些函数和变量与其他模块完全分离,哪些模块不可见。
我强烈建议将所有函数定义为静态函数,而不应从另一个C文件中调用该函数。
我觉得静态的这方面经常被忽视,而且每个人似乎都只关注愚蠢的"嘿,你可以通过多个函数调用来保持这个值"。尽管这通常是一个非常糟糕的主意,因为这样你就有了一个函数,每次你调用它时它的行为都是不同的。