【问题标题】:How are you intended to include files in a C project?您打算如何在 C 项目中包含文件?
【发布时间】:2013-02-13 11:03:04
【问题描述】:

我有三个文件。

trees.h
// a bunch of typedefs and function prototypes
#include <trees.c>

trees.c
// a bunch of function bodies

main.c
#include <trees.h>

这是不对的,因为trees.c 中的每个函数都会给我关于trees.h 中定义的类型的“未定义类型”错误。我已经尝试了所有我能想到的配置 - 包括来自 main 的trees.c 和来自trees.c 的trees.h,在trees.h 的末尾包括trees.c,在trees.h 的开头包括它。 .我能想到的每种包含的组合,每个组合都会给出一组不同的错误。有时是多个定义,有时是未定义的函数...

那么这究竟是如何工作的呢?我应该在哪些文件中放入什么,包含哪些文件以及放在哪里?

【问题讨论】:

  • 你为什么要在任何东西中包含tree.c
  • 预处理指令#include 基本上将您包含的文件的内容复制到您指定此包含的位置(请参阅msdn.microsoft.com/en-us/library/36k2cdd4%28v=vs.71%29.aspx)。因此,您的 #include 是您出现这种未定义类型错误的原因:您在原型之前复制了函数的实现。

标签: c include


【解决方案1】:

像这样:

trees.h
// a bunch of typedefs and function declarations (prototypes)

trees.c
#include <trees.h>
// a bunch of function definitions (bodies)

main.c
#include <trees.h>

说明:

#include 与将整个包含文件复制到此文件(您放置#include 的位置)基本相同。

因此在main.c 中包含trees.h 允许该文件了解trees.c 中的函数。

trees.c 中包含trees.h 允许trees.c 中较低的函数可用,这也是trees.c 中使用的定义等被指定的地方。

您也可能不知道如何创建多个对象并将它们链接起来,请参阅 Joachim Pileborg 的回答。

(非常丑陋的)替代方案是:

trees.h
// a bunch of typedefs and function declarations (prototypes)

trees.c
#include <trees.h>
// a bunch of function definitions (bodies)

main.c
#include <trees.c>

那么你只需要编译main。但是对于任何有几个.c 文件的项目,这变得不切实际。

【讨论】:

  • 但是在第一个例子中,main.c 是如何知道trees.h 中函数的定义是什么?为什么编译器不只是抛出某种“没有定义的函数原型”错误?它是如何知道在 trees.c 中查找这些定义的?
  • @JackM:在第一个示例中,编译器在编译 main.c 时不会查看trees.c。编译 main.c 所需的只是原型,而不是函数体。链接器稍后将需要函数体,这就是为什么您需要了解如何创建多个目标文件并链接它们。
【解决方案2】:

您将每个源文件编译成目标文件,然后将这些目标文件链接在一起形成最终的可执行文件。如果你使用例如GCC 并在命令行上编译,您可以将两个源文件都放在命令行中,GCC 会为您处理:

$ gcc main.c tree.c -o tree

上面的命令告诉gcc编译和链接文件main.ctree.c,并将输出的可执行文件命名为tree。也可以将源文件单独编译成目标文件,然后手动链接起来:

$ gcc -c main.c -o main.o
$ gcc -c tree.c -o tree.o
$ gcc main.o tree.o -o tree

在上述命令中,-c 选项告诉gcc 创建一个目标文件,-o 选项告诉gcc 为该目标文件命名。最后一个命令获取这些目标文件并创建最终的可执行文件并将其命名(使用-o 选项)tree

在源文件中,您包含所需的标头,而不是相反。

【讨论】:

    【解决方案3】:

    它不起作用的原因是你必须使用'extern'来定义一个变量或函数,该变量或函数在与标准不同的包含文件中声明。您还应该将所有头文件保存为 *.h。因此,假设您在 tree.h 中定义了结构“树”:

    #include <tree.h>
    
    int main() {
        extern tree; /* Get variable 'tree' declared in tree.h */
        extern make_tree(void); /* Get function make_tree() declared in tree.h */
    
        make_tree(); /* Call function */
        return (0); /* End */
    }
    

    【讨论】:

      【解决方案4】:

      从不包括实现 (.c) 文件开始。仅包含标头 (.h) 文件。只要您需要在其中声明的类型或函数,就包括它们。为避免多次声明,请使用包含守卫(无论它们是什么 - 只需 google 即可)。

      【讨论】:

        【解决方案5】:

        要走的路是将头文件trees.h包含在trees.c中,然后将trees.c包含在main.c中

        看看这个帖子here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-10-12
          • 1970-01-01
          • 2022-01-05
          • 2019-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多