我是C的新手。我面前有一本书,解释了C的“文件范围”,包括示例代码。但是代码只声明并初始化一个文件范围的变量 - 它不会通过尝试以非法方式访问它来验证变量的范围。所以!本着科学的精神,我构建了一个实验。
档案bar.c
:
static char fileScopedVariable[] = "asdf";
档案foo.c
:
#include <stdio.h>
#include "bar.c"
main()
{
printf("%s\n", fileScopedVariable);
}
根据我的书和Google,对printf()
的调用应该会失败 - 但事实并非如此。 foo.exe
输出字符串“asdf”并正常终止。我非常想使用文件范围。我错过了什么?
答案 0 :(得分:15)
你#included bar.c,它会导致预处理器在编译器接触之前将bar.c的内容字面复制到foo.c中。
尝试删除include,但告诉编译器编译这两个文件(例如gcc foo.c bar.c
)并按预期观察它。
编辑:我认为主要的困惑在于编译器和预处理器之间。语言规则由编译器强制执行。预处理器在编译器之前运行,并对那些以#为前缀的命令起作用。所有预处理器都是操作纯文本。它不解析代码或尝试以任何方式解释代码的含义。 “#include”指令非常直观 - 它告诉预处理器“在这里插入此文件的内容”。这就是为什么你通常只在.h(头文件)文件上使用#include,而你只在头文件中放置函数原型和外部变量声明。否则,您将最终编译相同的函数,或多次定义相同的变量,这是不合法的。
答案 1 :(得分:6)
这是由于令人困惑的条款造成的。 C中的file scope
并不是指将标识符限制为仅与一个翻译单元的链接。它也不意味着范围仅限于一个物理文件。相反,file scope
表示您的标识符是全局的。这里的术语file
是指处理所有#include
,#define
和其他预处理器指令所产生的文本。
一般而言,范围只是在一个翻译单元中生效的概念。当涉及多个编译时,链接开始发生。
如果声明文件范围变量static
,则它会给出变量内部链接,这意味着它在该转换单元之外是不可见的。
如果您没有显式声明它,或者声明文件范围变量extern
,那么其他翻译单元可以看到它们:如果它们声明具有相同标识符的文件范围变量,将该标识符 link 添加到同一个变量中。
在您的情况下,bar.c
加入foo.c
会将fileScopeVariable
的定义插入正在编译的翻译单元中。因此,它在该单元中可见。
答案 2 :(得分:2)
不要永远 #include .c文件就像你在那里做的那样。语言允许它,但是C编码器就是不这样做,所以如果你这样做,你会把人们混淆。最有可能包括你自己。
“#include”表示“编译器,在开始编译我的代码之前,请转到另一个文件并将其粘贴到此文件的前面。”
我曾经因为其中一个vxWorks源文件这样做而迷失了一整天。我仍然对他们过火了。
答案 3 :(得分:0)
删除第二条include指令。如上所述...
在编译代码之前,编译器会对其进行预处理。在那个阶段,它处理所有以'#'开头的指令,如#include,#define等。
要查看该阶段的结果,您只需运行'gcc -E'(如果您使用的是gcc)。