【问题标题】:Several doubts about (#include)ing non standard libraries关于(#include)非标准库的几个疑问
【发布时间】:2019-05-24 21:50:05
【问题描述】:

假设我在一个文件中编写了一些函数,我们将其称为foo.c。 这是foo.c

int d;

typedef int bar;

int foo(int a, int b){
 ...
}

void boo(){
 ...
}

char *test(){
 ...
}

现在,boo 是仅在 foo.c 中使用的函数,而 foo()test()dBool 需要能够在其他文件中被调用。

为了做到这一点,我知道我必须创建一个foo.h 文件并这样写:

extern int d;
extern typedef int bar;
int foo(int a, int b);
char *test();

然后#include "foo.h"foo.c 文件中,并且每当我想使用foo.c 中定义的类型和函数时,我必须在我想使用的文件中包含foo.hfoo.c foo.c 函数和类型。

所以foo.c 最终会是这样的:

#include "foo.h"

int d;

typedef int bar;

int foo(int a, int b){
 ...
}

void boo(){
 ...
}

char *test(){
 ...
}

这是我的问题。

第一季度。这是你实际做的吗?既然foo.h 已经包含在foo.c 中,那么在我想使用其功能的文件中仅包含foo.c 是否就足够了?我不能直接在 foo.c 文件中定义函数,根本不使用 foo.h 文件吗?

第二季度。你真的必须将extern 放在foo.h 文件中的typedef 前面吗?

第三季度。假设在 foo.c 中,我使用了一些标准 C 库,例如 string.h 和 math.h 。我应该在哪里包括它们?直接在foo.c 文件中,在foo.h 文件中还是在两者中?是否需要 #ifndef 指令?如果有,你如何正确使用它们?

第四季度。写完foo.cfoo.h 文件后,我准备好了吗?就像,我不需要编译它们或任何东西,对吧?我可以在任何需要的地方#include他们吗?

Q5。我在其他地方读到,如果我想使用自定义库,这些是我需要遵循的步骤:

  • 定义接口 (foo.h)
  • foo.c #include ing foo.h
  • 创建这样的目标文件gcc -o foo.o -c foo.c
  • 在我想使用foo.c函数的程序中包含foo.h
  • 像这样链接目标文件gcc my_proj.c foo.o

这些步骤真的有必要吗?因为我没有在其他地方看到他们提到过。为什么我只需要在要使用foo.c 函数的文件中包含foo.h?目标文件到底是什么?

感谢您的宝贵时间,如果有点冗长,请见谅

【问题讨论】:

  • wouldn't it be sufficient to include only foo.c - 从不包含 C 文件(即具有实际代码的文件),仅包含 H 文件(即具有函数声明和/或预处理器定义的文件)。
  • typedef Bool 不是一个好主意 int
  • “我不需要编译它们什么的,对吗?” 对,只要你的唯一目的是编写 C 源代码,并且从不执​​行它。还是我理解错了?
  • 你应该阅读一点关于编译和链接的区别。 ...和翻译单元。
  • @FoxyIT 好吧,这是人们能想到的最糟糕的例子之一。请称它为 typedef int bar; 或 bool 以外的任何名称

标签: c


【解决方案1】:

第一季度。这是你实际做的吗?既然 foo.h 已经包含在 foo.c 中,那我想在其中使用它的功能的文件中只包含 foo.c 还不够吗?

您只是不包含 .c 文件。在您的情况下, foo.c 和其他文件是单独的编译单元,它们最终链接在一起。

第二季度。在 foo.h 文件中,您真的必须将外部放在 typedef 前面吗?

不,typedef 不需要extern

第三季度。假设在 foo.c 中我使用了一些标准 C 库,例如 string.h 和 math.h 。我应该在哪里包括它们?直接在 foo.c 文件中,在 foo.h 文件中还是在两者中? #ifndef 指令是否必要?如果有,你如何正确使用它们?

如果您在.h 中也需要这些文件,请将它们包含在其中(例如,用于函数原型中使用的类型)。如果您仅在 .c 中需要它们,请将它们包含在其中。

第四季度。写完 foo.c 和 foo.h 文件后,我准备好了吗?就像,我不需要编译它们或任何东西,对吧?我可以像这样在任何需要的地方#include 它们?

您可以编译它们以获得可调用的东西。如果你不编译你的程序,你就不能使用它。还是我理解错了?

Q5。我在其他地方读到,如果我想使用自定义库,这些是我需要遵循的步骤:

[剪辑]

确实,这是一种方法。由于显而易见的原因,步骤 1、2 和 4 不能省略。但是您可以通过以下方式一起执行第 3 步和第 5 步

gcc my_proj.c foo.c

这会编译给定的文件,然后在一次调用中将它们链接在一起。

为什么我只需要在要使用 foo.c 函数的文件中包含 foo.h?

这是因为生成的目标文件包含有关链接器需要其他目标文件中的哪个函数的信息。

目标文件到底是什么?

这是编译一个源文件的结果。如果您将多个目标文件链接在一起,您将获得一个正在运行的可执行文件。

换句话说:目标文件是源文件的编译版本。它“提供”其他目标文件所需的标识符,并且它“要求”其他文件提供的其他标识符。将它们链接在一起意味着所需的对象和提供的对象以适当的方式连接起来,以便程序可以运行。

示例:您有一个 foo.c,它定义了函数 footest。然后你有一个 main.c,它利用了这些函数并提供了一个函数main。最后,将它们链接在一起并与启动程序所需的启动代码组合在一起,该代码调用main()main() 中分别调用foo()test() 的点以特殊方式标记,以便链接器可以将实际调用地址放在那里。

【讨论】:

  • 所以基本上只包含 foo.h 文件就足够了,因为稍后在将 proj.c 文件与 foo.o 文件链接时,程序会看到每个函数定义实际上做了什么?链接这两个文件时,foo.h 不会被定义两次,因为它已经在 foo.c 中定义了吗?
  • 另外,如果我在 foo.c 文件中包含一些标准 C 库,然后在 proj.c 文件中重新包含它们……我会遇到什么问题吗?
  • @FoxyIT 包含一个文件仅意味着它的内容在包含文件中是已知的。这就是为什么在 .h 文件中只有声明,没有定义。 (见here两者的区别。)如果你遵循这个原则,就不会出现这种问题。
【解决方案2】:

第一季度。你真的是这样做的吗?

没有

既然 foo.h 已经包含在 foo.c 中,难道还不够 在我想在其中使用其功能的文件中仅包含 foo.c?

您应该只包含.h 文件;无论是在定义它们的文件中,还是在使用它们的文件中。另外,该包含应该是定义函数的文件中的第一个,但在使用它们的文件中,它应该在其余部分之后(标准头文件,其他包的头文件,...);这样做的原因是为了容易检测错误。

我不能直接在 foo.c 文件中定义函数吗? 根本不使用 foo.h 文件?

通常,不会。只有 static inline 函数应该这样做。

第二季度。你真的必须把 extern 放在 typedef 前面吗? foo.h 文件?

没有:typedef int foobar_t;

第三季度。假设在 foo.c 中我使用了一些标准 C 库,例如 string.h 和 math.h 。我应该在哪里包含它们?

在需要它们的文件中 (foo.c)。在每个文件中只包含它需要的标题。不再;不少。

直接在 foo.c 文件中、在 foo.h 文件中还是在两者中?

foo.c

#ifndefinstructions 是否必要?如果是这样,你如何使用它们 正确吗?

是的:

// foo.h
#ifndef FOO_H
#define FOO_H

Here go all the contents of foo.h

#endif     /* foo.h */

第四季度。写完 foo.c 和 foo.h 文件后,我准备好了吗? 就像,我不需要编译它们或任何东西,对吧?我可以 只需像这样将它们#include 到我需要的任何地方?

您需要将foo.c 编译成foo.o(目标文件),然后您可能想做一个静态库(.a)或动态库。你可以在任何你想要的地方包含它,但是你需要准备你的 Makefile 来这样做。

Q5。如果我想使用自定义库,我在其他地方读过 这些是我需要遵循的步骤:

定义接口(foo.h)

编写 foo.c #include ing foo.h

创建一个像这样的目标文件 gcc -o foo.o -c foo.c

在我想使用 foo.c 函数的程序中包含 foo.h

像这样链接目标文件 gcc my_proj.c foo.o

这些步骤真的有必要吗?

是的

因为我没有在其他任何地方看到他们提到过。为什么我只 需要在我想要的文件中包含 foo.h 使用 foo.c 函数?

阅读有关编译和链接的更多信息。

目标文件到底是什么?

一个编译的文件。其中许多通常链接在一起以生成可执行文件。

【讨论】:

  • 关于这个问题的答案:Are #ifndefinstructions necessary? If so, how do you use them correctly? 必须在 foo.h 文件中完成,对吧?不是项目。 and then you probably would like to do a static library (.a) or a dynamic one. You can include it wherever you want, but you will need to prepare your Makefile to do so.这部分我也不是很懂
  • @FoxyIT 1) 是,在所有 .h 文件中,并且仅在 .h 文件中
  • @FoxyIT 2) 你不应该担心它。手动链接目标文件,这比较容易,当你玩够了,完全了解如何使用它们时,你可以尝试做一个库,如果你有任何问题,可以在这里提问。 :)
猜你喜欢
  • 1970-01-01
  • 2014-08-17
  • 2021-10-04
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
相关资源
最近更新 更多