我正在学习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);
}
输出如下:
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'并打印其值;由于main中没有名为“ b”的局部变量,同一printf()语句访问全局'b'。静态和全局int变量的值为0。这就是为什么main()中的printf语句将0打印为b的值。”
我的印象是C中的静态变量仅声明一次并且具有全局范围,而且所有全局变量都是隐式静态的。那么,鉴于全局变量的隐式声明或main中的显式声明的全局范围,可以在不同的范围中重新声明这些静态变量是正确的吗?如果内存中只有一个静态变量,并且它具有全局作用域,那么该程序中如何以相同的名称阻止特定的静态变量?
谢谢
答案 0 :(得分:5)
我会尽可能简洁地为您提供帮助。 以下语句在C语言中仅不为真:
全局变量可以是静态或非静态(常规)。不同之处在于,常规全局变量可以被其他翻译单元(简称C文件)使用,而静态变量则不能。
让我给你一个例子。假设您有两个C文件,即a.c和b.c。 在交流中:
int my_global_var;
static int a_static_var;
在b.c:
extern int my_global_var;
static int a_static_var;
int main() { /* ... */ }
您可以使用这两个C文件来构建程序,这种方式[假设您使用的是Linux]:
gcc -c a.c
gcc -c b.c
gcc -o prog a.o b.o
现在,两个文件中的变量my_global_var
是 same ,但在a.o
翻译单元中是 instantiated (bc看到作为 extern 变量)。尽管变量a_static_var
不是唯一。每个翻译单元都有自己的a_static_var
变量:它们是完全不相关的。
回到您的示例,静态变量也可以具有函数作用域:在这种情况下,在不同函数内定义的静态变量完全不相关,与全局方法相同独立翻译单元中的静态变量无关。在您的情况下,您可以考虑两个静态a
,如果它们分别称为__main_a
和__prtFun_b
。实际上,这非常接近编译程序时内幕发生的情况。
现在,要完成图片,有一条规则允许您定义局部(静态或非静态)变量,即使该变量会隐藏用相同名称定义的全局变量。因此,例如在prtFun()
中,当您访问b
时,您正在访问本地非静态变量,而当您访问a
时,您正在访问本地静态{{1 }}变量。 a
也是如此。在任何情况下,您的代码都不会触及全局main()
变量。
希望我能对您有所帮助。
答案 1 :(得分:1)
即使vvaltchev已经提供了很好的解释,我还是想添加一两件事...
大多数书籍,教程等都使用静态代码(如代码所示)来保留多个函数调用中的局部变量值。但是,这仅是static的用途之一,而且-在我看来-更为无用。
让我们重新审视此声明
全局变量可以是静态或非静态(常规)。区别在于常规全局变量可以被其他翻译单元(简而言之是C文件)使用,而静态变量不能。
此静态用法未在您的代码中得到证明,但确实非常有用,因为它实质上意味着您可以定义“私有”的变量(和函数!),并且永远不会在其他c文件中看到。这样就可以清晰地分开,哪些功能和变量应该在其他模块中可见,而哪些则不应该。
我强烈建议将所有函数定义为静态函数,不应从另一个c文件内部调用该函数。
我觉得静态化的这一方面经常被忽视,每个人似乎只专注于愚蠢的“嘿,您可以在多个函数调用中保留该值”。即使这通常是一个非常糟糕的主意,因为这样您就有了一个函数,每次调用它时都会表现不同。