关于编译和库的两个基本问题

时间:2009-08-27 10:22:10

标签: c

我有两个半相关的问题。

我的第一个问题:我可以通过以下方式调用标准库中的函数而不编译整个库:

#include <stdio.h>

我如何使用我的头文件做同样的事情?只是“包含”我的纯文本头文件显然不起作用。

#include "nameofmyheader.h"

基本上,我如何创建其他文件可以调用的库?

第二个问题:假设我有一个程序被分成50个c文件和一个头文件。除此之外,编译它的正确方法是什么:

cc main.c 1.h 1.c 2.c 3.c 4.c 5.c 6.c 7.c   /*... and so on*/

请纠正我的任何误解。我完全迷失在这里。

5 个答案:

答案 0 :(得分:14)

首先,你对#include的情况感到有些困惑。你永远不会“编译”标准库。标准库已经编译好并且位于库文件中(Windows上的.dll和.lib文件,Linux上的.a和.so文件)。 #include的作用是为链接所需的声明提供标准库。

首先要了解#include指令,它们是非常低级的。如果您使用Java或Python编程,则#includes与导入有很大不同。 Imports在高级别告诉编译器“此源文件需要使用此包”,编译器会计算出如何解决该依赖关系。 C指令中的#include说“获取此文件的全部内容,并在编译时直接将其粘贴到此处”。特别是,#include <stdio.h>引入了一个文件,该文件具有标准库中所有I / O函数的前向声明。然后,当您编译代码时,编译器知道如何调用这些函数并检查它们的类型正确性。

编译完程序后,链接到标准库。这意味着您的链接器(由编译器自动调用)将导致您的可执行文件使用共享标准库(.dll或.so),或者将复制静态标准库所需的部分(.lib或.a)进入你的可执行文件。在任何情况下,您的可执行文件都“包含”您不使用的标准库的任何部分。

至于创建一个图书馆,这是一个复杂的话题,我会把它留给其他人,特别是因为根据你的问题的下一部分,我认为这不是你真正想要的。

头文件并不总是库的一部分。看来你拥有的是多个源文件,并且你希望能够在另一个源文件中使用来自一个源文件的函数。您可以在不创建库的情况下执行此操作。您需要做的就是将您希望从其他地方访问的foo.c的声明放入foo.h.声明是函数原型和“extern”变量声明之类的东西。例如,如果foo.c包含

int some_global;

void some_function(int a, char b)
 {
     /* Do some computation */
 }

然后,为了使这些文件可以从其他源文件访问,foo.h需要包含

extern int some_global;

void some_function(int, char);

然后,只要您想使用some_global或some_function,就可以#include "foo.h"。由于标题可以包含其他标题,因此通常将标题包装在“include guard”中,以便声明不会重复。例如,foo.h应该真的读到:

#ifndef FOO_H
#define FOO_H

extern int some_global;

void some_function(int, char);

#endif

这意味着每个编译单元(源文件)只会处理一次标题。

至于如何编译它们,永远不要将.h文件放在编译器命令行上,因为它们不应包含任何可编译代码(仅声明)。在大多数情况下,编译为

是完全可以的
cc main.c 1.c 2.c 3.c ... [etc]

但是,如果您有50个源文件,那么使用构建系统可能会更方便。在Linux上,这是一个Makefile。在Windows上,它取决于您使用的开发环境。您可以谷歌,或者在指定平台后提出另一个问题(因为这个问题已经相当广泛)。

构建系统的一个优点是它们独立编译每个源文件,然后将它们全部链接在一起,这样当您只更改一个源文件时,只需要重新编译该文件(和程序)重新链接)而不是重新编译所有内容,包括没有改变的东西。当程序变大时,这会产生很大的时间差异。

答案 1 :(得分:0)

您需要创建一个共享库,标准库是一个在程序中隐式链接的共享库。

拥有共享库后,您可以使用.h文件,只需使用-lyourlib编译程序,这对于libc是隐式的

使用以下方式创建一个:

gcc -shared test.c -o libtest.so

然后编译你的程序,如:

gcc myprogram.c -ltest -o myprogram

对于你的第二个问题,我建议你使用Makefiles http://www.gnu.org/software/make/

答案 2 :(得分:0)

如果你真的希望它只是包含一个.h文件那么简单,你所有的“库”代码都需要在.h文件中。但是,在这种情况下,有人只能将.h文件包含在一个且仅包含一个.c文件中。这可能没问题,取决于某人如何使用您的“图书馆”。

答案 3 :(得分:0)

您可以将多个.c文件合并到库中。这些库可以与其他.c文件链接,成为可执行文件。

您可以使用makefile创建一个大项目。

makefile有一组规则。每条规则都描述了创建程序的一部分以及它们与其他部分或源文件的依赖关系所需的步骤。

答案 4 :(得分:0)

标准库已经已完成并已放置在您的计算机上,可以动态链接。这意味着程序在需要时动态加载库。将其与运行编译器/链接器时编译为INTO程序的静态库进行比较。

这就是您需要编译代码而不是标准库代码的原因。您可以自己构建一个动态(共享)库。

作为参考,#include <stdio.h>不会导入标准库。它只允许编译和链接查看库的公共接口(知道使用了什么函数,它们采用了什么参数,定义了什么类型,它们的大小等)。

Dynamic Loading

Shared Library

您可以将文件拆分为模块,然后创建共享库。但通常随着项目变得越来越大,您往往需要一种更好的机制来构建您的程序(和库)。您需要使用make程序或GNU Build System之类的完整构建系统,而不是在需要进行重建时直接调用编译器。