C中的静态库

在上一篇博客文章中,我们了解了编译过程,并且在链接部分中,编译器将二进制代码连接到库,然后返回可执行文件。 现在让我们详细讨论这些库。

首先…什么是图书馆? 井库是一个包含几个目标文件的文件。 好的……但这意味着什么,这些文件是如何到达那里的? 回答这个问题可能会提示其他问题,因此让我们看看C中的静态库是关于什么的。 在这里,我们将学习它们如何工作,为什么使用它们,如何创建它们以及如何使用它们。

  1. 他们如何工作?

在编译过程的最后阶段,链接器生成可执行文件时,它还会添加(从库中复制)我们在程序中使用的函数的代码。 该功能是静态库的一部分,我们将其包含在代码中,以便能够使用该功能。 对于静态库中代码中的每个函数,链接器都将在可执行文件中包含该函数的代码。 如果我们在同一个程序中使用很多功能,这将是一个问题,因为对于每个我们包含的功能,程序的大小都会增加,因为我们正在将该功能的代码复制到可执行文件中。

静态链接的另一个问题是可移植性。 那么,当我们移动该可执行文件时会发生什么? 没有! 这就是问题所在。 如果同时对库进行了某些更改或库已被更新,则这些更改将不会反映在我们的程序中,除非我们使用更新后的库重新对其进行编译。

2.为什么我们使用它们?

现在必须怀疑……如果库增加了程序的大小,并且每次对程序进行一些更改时都重新编译它,我们为什么还要使用库? 但是,即使存在静态库的这些缺点; 如果您考虑一下,如果您移动程序并且没有库需要链接,该怎么办。 在这种情况下,代码已经复制到您的可执行文件中,您不必担心。 同时,这使程序的分发和安装更加容易。

但是您可能会问为什么我们使用它们? 您是否曾经在不同的程序中一遍又一遍地编写相同的代码,并且希望有一种神奇的方法跳过该部分。 好吧,这就是图书馆的工作。 您可以将这些代码片段添加到库中,而只需在编译过程中包含一个库,编译器便会在需要时将其插入程序中,而无需一遍又一遍地编写。

现在,让我们看看如何实现这一目标。

3.创建一个静态库

用于创建静态库的基本工具是一个名为“ ar”的程序,用于“存档”,这就是在命令行中的样子。

ar rc lib name_of_your_library_here .a file1.o file2.o file3.o

此命令创建一个名为“ lib name_of_your_library .a”的静态库,并将对象文件“ file1.o”,“ file2.o”和“ file3.o”的副本放入其中。 每个库名称都 以lib开头,以.a扩展名结尾

让我们看一些例子。

首先,我们编写一些程序来单独执行一些我们经常使用的任务,并将所有原型都写入头文件中。 现在,为了将所有目标文件放入我们的库中,我们首先需要从所有这些.c文件中创建目标文件,我们使用gcc对其进行编译,但是使用选项-c可以返回相同的文件名,但作为对象文件,扩展名为.o。 现在,那些.o文件是我们要保存在库中的目标文件(在示例中名为my_lib),我们通过使用上述命令ar和’ rc ‘选项来执行此操作,以防万一库不存在被创建c选项 ),并且万一确实将旧文件替换为新文件( r选项 )。

为了确保所有目标文件均已正确添加到库中,我们可以使用ar -t显示列出存档内容的表。

创建存档或对其进行修改后,我们需要对其进行索引。 为什么我们要这样做? 就像在寻找书中的特定章节时一样,您可以查看目录以更快地找到它。 如果我们的存档已建立索引,则编译器会执行相同的操作。 为了索引我们的库(存档),我们运行以下命令:

ranlib lib name_of_your_library_here .a

4.如何使用C库

因此,我们创建了我们的库,现在我们希望看到它的实际效果,所以这就是我们的操作方法。 为此,我们将库名称添加到提供给链接器的目标文件名称列表中。 为此,我们使用一个特殊的标志-l附加在我们的库名前面,开头不带lib,结尾带.a。 Linker会为我们解决这个问题。 标记-L。 告诉链接器在给定目录中可能找到库。 所以我们正在看这样的东西:

gcc main.c -L。 -l name_of_your_library_here -o your_exe_file_name

这将使用从main.c创建的目标文件main.o以及我们从指定的静态库中使用的任何函数来创建程序。

让我们也看一下示例。

现在我们知道,仅在编译过程中添加库就可以节省大量时间,因为静态库允许我们向其中添加不想一遍又一遍地写的函数。

编码愉快!!