Ansi C - K&R 编程语言书籍 - 头文件包含

Ansi C - programming language book of K&R - header file inclusion

阅读 K&R ansi C 编程语言书籍(第二版),第 82 页给出了编程 files/folders 布局的示例。

我不明白的是,虽然 calc.h 包含在 main(函数的使用)、getop.c(getop 的定义)和 stack.c( push 和 pop 的定义),它不会包含在 getch.c 中,即使 getchungetch 在那里定义。

calc.h 包含 getch() 和 ungetch() 的 声明。它包含在想要使用这些功能(因此需要他们的签名)的文件中。

getch.c 相反,包含 getch() 和 ungetch() 的 定义 。因此,不需要包含它们的声明(在定义中隐式定义)。

虽然包含头文件是个好主意,但它不是必需的,因为 getch.c 实际上 使用 calc.h 中声明的函数,它如果它只使用 getch.c.

中已经定义的那些,甚至可以通过

包含头文件是个好主意的原因是,如果您使用现代风格的原型和定义,它会提供一些安全性。如果例如 getop 没有在 getop.c 中定义,编译器应该会抱怨,并且具有与 calc.h.

中相同的签名

您如此恰当地发现的遗漏可能是真正问题的根源。为了充分受益于 C 在 multi-translation-unit 程序中的静态类型检查(这几乎是任何重要的事情),我们必须确保定义外部名称(例如函数)的站点以及定义外部名称的所有站点引用名称,在范围内具有相同的声明,最好来自单一来源:一个 header 声明该名称的文件。

如果定义在范围内没有声明,则可以更改定义,使其不再与声明匹配。该程序仍将转换 link,从而在调用函数或使用 object 时导致未定义的行为。

如果你使用 GNU 编译器,你可以使用 -Wmissing-prototypes 来防止这个问题。直接来自 gcc 手册页:

       -Wmissing-prototypes (C and Objective-C only)
           Warn if a global function is defined without a previous prototype
           declaration.  This warning is issued even if the definition itself
           provides a prototype.  The aim is to detect global functions that
           fail to be declared in header files.

如果不进行诊断,这种事情,例如忘记 header 文件,可能会发生在我们最好的人身上。

忘记 header 的一个可能原因是示例项目使用了 "one big common header" 约定。 "one big common header" 方法让程序员忘记所有关于 header 的事情。一切都只是看到其他一切,而使它起作用的 #include "calc.h" 只是一个很小的脚注,可能会被健忘症吞没。 :)

另一个方面是作者花了很多时间在 pre-ANSI "Classic" C 中进行编程而没有原型声明。在经典 C 中,header 文件主要用于普通类型声明和宏。习惯是,如果源文件不需要某些 header 中定义的类型或宏,则不需要包含 header。这种习惯的死灰复燃可能就是这里发生的事情。