C静态作用域语义

时间:2018-12-30 11:49:58

标签: 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);
}

输出如下:

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中的显式声明的全局范围,可以在不同的范围中重新声明这些静态变量是正确的吗?如果内存中只有一个静态变量,并且它具有全局作用域,那么该程序中如何以相同的名称阻止特定的静态变量?

谢谢

2 个答案:

答案 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文件内部调用该函数。

我觉得静态化的这一方面经常被忽视,每个人似乎只专注于愚蠢的“嘿,您可以在多个函数调用中保留该值”。即使这通常是一个非常糟糕的主意,因为这样您就有了一个函数,每次调用它时都会表现不同。