关于(#include)非标准库的一些疑问

时间:2019-05-24 13:13:10

标签: c

让我们假设我在文件中编写了一些函数,我们将其称为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(){
 ...
}

这是我的问题。

Q1。这是您实际的做法吗?由于foo.h已包含在foo.c中,在我要使用其功能的文件中仅包含foo.c不够吗?我不能直接在foo.c文件中定义函数,而不完全不使用foo.h文件吗?

Q2。您实际上是否必须将extern文件中的foo.h放在typedef前面?

Q3。假设在foo.c中,我使用了一些标准的C库,例如string.h和math.h。我应该在哪里包括它们?是直接在foo.c文件中,还是直接在foo.h文件中?是否需要#ifndef指令?如果是这样,您如何正确使用它们?

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

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

  • 定义界面(foo.h
  • foo.c #includeing foo.h
  • 创建像这样的gcc -o foo.o -c foo.c
  • 对象文件
  • 在要使用foo.h函数的程序中包含foo.c
  • 像这样gcc my_proj.c foo.o链接目标文件

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

感谢您的宝贵时间,如果这有点冗长

2 个答案:

答案 0 :(得分:3)

  

Q1。这是您实际的做法吗?由于foo.c已经包含foo.h,在我要使用其功能的文件中仅包含foo.c不够吗?

您只是不包括.c文件。就您而言,foo.c和其他文件是单独的编译单元,它们最终链接在一起。

  

Q2。您实际上是否必须将外部文件放在foo.h文件中的typedef前面?

否,typedef不需要extern

  

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

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

  

Q4。编写foo.c和foo.h文件之后,我都准备好了吗?就像,我不需要编译它们或任何东西,对吗?我可以只在需要的地方#include他们吗?

您可以编译它们以获得可调用的对象。如果不编译程序,则无法使用它。还是我理解你错了?

  

Q5。我在其他地方读到过,如果我想使用自定义库,则需要遵循以下步骤:

     

[snip]

实际上,这是一种方法。出于显而易见的原因,不能省略步骤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()的点以特殊方式标记,以便链接器可以在其中放置实际的呼叫地址。

答案 1 :(得分:1)

  

Q1。这是您的实际操作方式吗?

  

因为foo.h已经包含在foo.h中,这是否足以   我要使用其功能的文件中仅包含foo.c?

您应仅包含.h个文件;既在定义它们的文件中,又在使用它们的文件中。另外,include应该是定义函数的文件中的第一个,但是在使用它们的文件中,它应该排在其余的后面(标准标头,其他软件包的标头,...);这样做的原因是易于发现错误。

  

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

通常,不会。只有static inline函数可以做到这一点。

  

Q2。您实际上是否必须将外部放在typedef前面   foo.h文件?

否:typedef int foobar_t;

  

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

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

  

是直接在foo.c文件中,在foo.h文件中还是在两个文件中?

foo.c

  

是否需要#ifn定义说明?如果是这样,您如何使用它们   正确吗?

是:

// foo.h
#ifndef FOO_H
#define FOO_H

Here go all the contents of foo.h

#endif     /* foo.h */
  

Q4。编写foo.c和foo.h文件后,我都准备好了吗?   就像,我不需要编译它们或任何东西,对吗?我可以   只是在我需要的地方包括它们?

您需要将foo.c编译成foo.o(目标文件),然后您可能想做一个静态库(.a)或一个动态库。您可以在任何位置添加它,但是您需要准备Makefile来实现。

  

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

     

定义接口(foo.h)

     

写foo.c#include foo.h

     

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

     

要在其中使用foo.c函数的程序中包含foo.h

     

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

     

这些步骤真的必要吗?

  

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

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

  

什么是目标文件?

已编译文件。通常将它们中的许多链接在一起以生成可执行文件。