在C中,如何将全局变量的范围限制为声明它的文件?

我是C的新手。我面前有一本书,解释了C的“文件范围”,包括示例代码。 但是代码只声明并初始化一个文件范围的变量 – 它不会通过尝试以非法方式访问它来validation变量的范围。 所以! 本着科学的精神,我构建了一个实验。

文件bar.c

 static char fileScopedVariable[] = "asdf"; 

文件foo.c

 #include  #include "bar.c" main() { printf("%s\n", fileScopedVariable); } 

根据我的书和谷歌,对printf()的调用应该失败 – 但事实并非如此。 foo.exe输出字符串“asdf”并正常终止。 我非常想使用文件范围。 我错过了什么?

你#included bar.c,它会导致预处理器在编译器接触之前将bar.c的内容字面复制到foo.c中。

尝试摆脱包含,但告诉编译器编译两个文件(例如gcc foo.c bar.c )并观察它如你gcc foo.c bar.c抱怨。

编辑:我想主要的混淆是在编译器和预处理器之间。 语言规则由编译器强制执行。 预处理器在编译器之前运行,并对那些以#为前缀的命令起作用。 所有预处理器都是操作纯文本。 它不解析代码或尝试以任何方式解释代码的含义。 “#include”指令非常直观 – 它告诉预处理器“在这里插入此文件的内容”。 这就是为什么你通常只在.h(头文件)文件上使用#include,而你只在头文件中放置函数原型和外部变量声明。 否则,您将最终编译相同的函数,或多次定义相同的变量,这是不合法的。

这是由于令人困惑的条款造成的。 C中的file scope并不是指将标识符限制为仅与一个翻译单元的链接。 它也不意味着范围仅限于一个物理文件。 相反, file scope意味着您的标识符是全局的。 这里的术语“ file是指处理所有#include#include #define和其他预处理器指令所产生的文本。

一般而言,范围仅是在一个翻译单元内生效的概念。 当涉及多个编译时,链接开始发生。

如果将文件范围变量声明为static ,则它会给出变量内部链接,这意味着它在该转换单元之外是不可见的。

如果你没有显式地声明它,或者你声明文件范围变量extern ,那么它对其他翻译单元是可见的:如果它们声明具有相同标识符的文件范围变量,那么将具有该标识符链接到同一个变量。

在您的情况下,将bar.c包含到foo.cfileScopeVariable的定义插入到正在编译的转换单元中。 因此,它在该单元中可见。

不要像你在那里那样#include .c文件。 语言允许它,但是C编码员不这样做,所以如果你这样做,你会混淆人们。 最有可能包括你自己。

“#include”的意思是“编译器,请在开始编译我的代码之前,转到另一个文件并将其粘贴到这个文件的前面。”

我曾经完全迷失了一整天,因为其中一个vxWorks源文件就是这样做的。 我仍然对他们过火了。

删除第二个include指令。 如上所述……

在编译代码之前,编译器会对其进行预处理。 在那个阶段,它处理所有以’#’开头的指令,如#include,#define等。

要查看该阶段的结果,您可以运行’gcc -E’(如果您使用的是gcc)。