【问题标题】:C - Scope of C FunctionsC - C 函数的范围
【发布时间】:2016-05-28 03:07:38
【问题描述】:

如果这是一个初学者的问题,我深表歉意,但是在使用 C 语言工作了一段时间之后,我终于想澄清一下函数可以使用哪些类型的文件/函数。

我知道我们可以像这样使用 #include 宏显式包含其他文件:

#include bar.c

但是同一目录中的文件呢?假设我们有以下文件结构:

src-
   |
   a.c
   b.c

假设 a.c 有函数“foo()”,b.c 有“bar()”

即使没有在头文件中明确包含 b.c,我是否可以在 a.c 中调用 bar()?

那么在子目录中,例如以下:

src-
   |
   a.c
   |
   someFolder-
             |
             b.c

我还能在交流中访问 bar() 吗?

基本上,函数的范围(不包括在标头中)是如何定义的?

【问题讨论】:

  • 如果您将它们编译并链接在一起,是的。
  • 注意:不推荐#include bar.c。我们有头文件。
  • @SouravGhosh 甚至不是“不推荐”,而是完全错误的。 bar.c 周围应该有双引号。
  • @FUZxxl 取决于。如果.c 只包含声明怎么办?无论如何,扩展名没有多大用处。语法部分,我同意。 :)
  • @SouravGhosh:".c" 仍然是错误的扩展名。使用".h"

标签: c scope include linkage


【解决方案1】:

您将 scopelinkage 混淆了。

术语范围描述了一个标识符在给定上下文中是否对编译器可见。 C 语言已知的最广泛的范围是文件范围,这意味着标识符在预处理后从声明的点到翻译单元的末尾都是可见的。您可以通过声明任何标识符使其可见/已知,但使标识符可见并不意味着引用该标识符是指它在另一个文件中引用的内容。

链接 一词描述了两个标识符如何引用同一事物。存在三个级别的链接:没有链接,每个带有名称的标识符指代不同的事物。使用内部链接,同一翻译单元中的每个标识符都指代同一事物。使用外部链接,整个程序中的每个标识符都指向同一个东西。两个翻译单元中的两个标识符要引用同一个东西,你需要声明它们都具有外部链接。

这与如何获得声明无关。在公共头文件中写入int foo() 与在两个源文件中写入同一行没有区别。在任何一种情况下,所有标识符都引用相同的 foo(),因为函数具有外部链接,除非明确声明与 static 类型说明符具有内部链接。

它也与源代码的布局方式无关。只要将所有翻译单元链接到同一个二进制文件中,就可以在每个翻译单元中调用所有具有外部链接的函数。

【讨论】:

  • 啊,我明白了。在我的实际用例中,我正在浏览一些开源 C 代码,我感到很困惑,因为我注意到一些函数是从不同的文件中调用的,即使它们没有明确包含在内。当我真正浏览 Makefile 时,我现在可以看到“.o”文件正在链接在一起。感谢您的详尽解释
  • @Victor3y 我很高兴。
【解决方案2】:

取决于您是否将这些链接到一个二进制文件中。

如果链接 - 那么是的,可以使用隐式声明调用函数。

这种情况下的常见模式是制作包含所有声明的头文件,包括 *.c 文件通常不是首选,因为 #include 只是文件内容的文本包含

【讨论】:

    【解决方案3】:

    #include(一个预处理指令,不是宏,顺便说一句)有一个可配置的搜索目录列表。 如果您使用#include "something.h" 形式(与包含系统头文件的尖括号形式相比),列表中的第一个目录是包含文件的目录。

    虽然#include 进行了简单的文本包含,因此在技术上可以包含任何文本文件,但c 文件几乎从不包含。

    在 C 语言中,您通常将 c 文件单独编译为目标文件并将它们链接在一起,您所包含的是由声明组成的头文件,这些声明表示您当前编译单元不会的其他目标文件的接口见。

    查看http://www.cs.bu.edu/teaching/c/separate-compilation/ 或有关该主题的另一篇文章。

    【讨论】:

      【解决方案4】:

      正斜杠“/”在这种情况下应该可以工作。

      如果你可以毫无问题地包含foo.h,这意味着目录(比如C:\DIRFOO)是在编译器的“include”指令中预定义的。因此,可以通过#include <DIRBAR/bar.h> 包含子目录(例如C:\DIRFOO\DIRBAR)中的另一个文件(例如bar.h)。

      【讨论】:

        猜你喜欢
        • 2015-04-12
        • 2012-10-17
        • 2016-04-04
        • 2022-01-24
        • 1970-01-01
        • 2020-09-09
        • 2013-12-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多