"文件作用域"和"程序作用域"有什么区别?

24

全局声明的变量具有程序作用域。


使用static关键字全局声明的变量具有文件作用域。

例如:

int x = 0;             // **program scope**   
static int y = 0;      // **file scope**  
static float z = 0.0;  // **file scope** 

int main()  
{  
   int i;   /* block scope */  
   /* .
      .
      .
   */ 
   return 0;  
}  

这两者之间有什么区别?

4个回答

18

static声明的变量不能直接从其他文件访问。相反,如果在其他文件中将非static变量声明为extern,则可以从其他文件访问。

例如:

foo.c

int foodata;
static int foodata_private;

void foo()
{
    foodata = 1;
    foodata_private = 2;
}

foo.h

void foo();

main.c

#include "foo.h"
#include <stdio.h>

int main()
{
    extern int foodata; /* OK */
    extern int foodata_private; /* error, won't compile */

    foo();

    printf("%d\n", foodata); /* OK */

    return 0;
}

一般而言,应该避免使用全局变量。但在实际应用中,这些变量经常是有用的。通常将extern int foo;声明移到共享的头文件中(例如,在foo.h中)。


2
"extern int foodata_private" 可以被 编译,但无法链接。 - bool3max
为什么不将变量放在头文件中,在需要时使用它们,而不必使用任何 extern - Alexander Cska
@AlexanderCska,通常这不是一个好主意。如果该变量不是“静态的”,它将在包含头文件的每个源代码文件中被定义。然后程序可能会链接或不链接,具体取决于变量是否被初始化(有关详细信息,请参见https://dev59.com/oVDTa4cB1Zd3GeqPI2iJ)。两种结果几乎总是不是你想要的。如果该变量是“静态的”,它将在每个翻译单元中作为私有符号进行定义。同样,通常这也不是你想要的。 - Roman Dmitrienko
在 C 语言中,正确的方式在模块之间共享全局变量是在源代码文件中定义变量一次,并在相应的头文件中声明为 extern。然后,所有包含此头文件的源代码文件将正确地共享该变量。 - Roman Dmitrienko

17
在C99中,没有称之为“程序范围”的概念。在您的例子中,变量x具有文件范围,在翻译单元结束时终止。声明为static的变量yz也具有文件范围,但其链接是内部链接。

C99(6.2.2/3)如果对象或函数的文件范围标识符的声明包含存储类别说明符static,则该标识符具有内部链接

此外,变量x具有外部链接,这意味着名称x可以在其他翻译单元或整个程序中访问。

C99(6.2.2/5)如果对象的标识符声明具有文件范围且没有存储类别说明符,则其链接为外部链接。


5
评论中说:“x具有文件作用域,仅在翻译单元结束时终止”(这意味着它只在此单元中可见),以及“x可以被其他翻译单元访问”是技术上正确的,但可能会有点困惑。尽管如此,我发现维基百科页面http://en.wikipedia.org/wiki/Linkage_(software)同样令人困惑。问题在于“可访问”和“可见”不是相同的。 - Ying Zhang
6
阅读 C99 标准后,我大致明白了:假设 x 具有文件作用域和外部链接。如果想在另一个翻译单元中访问 x,则必须在那里也声明 x。然后由于这两个 x 是关联的,它们引用同一物体。 - Ying Zhang

0

C程序可以写在几个文件中,这些文件由链接器组合成最终的执行文件。如果您的整个程序都在一个文件中,则没有区别。但在包括使用不同文件中函数库的复杂软件的实际世界中,差异是显著的。


0
具有文件作用域的变量仅在其声明点到文件末尾可见。文件指包含源代码的程序文件。一个大型程序中可以有多个程序文件。 具有程序作用域的变量在整个程序中的所有文件(不仅仅是定义它的文件)、函数和其他块中都可见。 更多信息请查看:C语言中的作用域和存储类

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接