GCC链接库进行编译

为什么当信息已经以#include的forms存在于源文件中时,我们必须告诉gcc哪个库链接?

例如,如果我有一个使用线程的代码,并具有:

#include <pthread.h> 

我仍然需要在gcc中用-pthread选项编译它:

 gcc -pthread test.c 

如果我不给-pthread选项,它会给find线程函数定义的错误。

我正在使用这个版本:

 gcc --version gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 

这可能是绊倒初学者的最常见的事情之一。

在C中,有两个不同的步骤来构建一个程序,编译和链接。 为了您的问题,这些步骤将您的代码连接到两种不同类型的文件,标题和库。

C代码中的#include <pthread.h>指令由编译器处理。 编译器(实际上是预处理器)在将C文件转换为目标文件之前,将pthread.h的内容直接粘贴到代码中。

pthread.h是一个头文件,而不是一个库。 它包含您可以在库中找到的函数的列表,他们所采取的参数以及返回的内容。 一个头可以存在没有一个库,反之亦然。 头文件是一个文本文件,通常在Unix派生系统的/usr/include中。 你可以打开它就像任何C文件来读取内容。

命令行gcc -lpthread test.c执行编译和链接。 在过去,你会先做一些类似于cc test.c ,然后是ld -lpthread test.o 正如你所看到的, -lpthread实际上是链接器的一个选项。

链接器不知道任何有关C代码或标题的文本文件。 它只适用于编译的目标文件和现有的库。 -l标志告诉它要查找哪些库来查找正在使用的函数。

标题的名称与库的名称无关。 这是事故。 大多数情况下,图书馆提供了许多标题。

特别是在C ++中,每个类通常有一个头,而且库通常提供来自相同名称空间的类实现。 在C中,头文件被组织起来,它们包含一些常用的函数子集 – math.h包含数学运算, stdio.h提供IO函数等。

他们是两个不同的东西。 .h文件包含声明,有时也包含内联函数。 众所周知,每个职能都应该有一个实现/定义来工作。 这些实现是分开保存的。 例如, -lpthread是以二进制形式保存functions declared in headersfunctions declared in headersfunctions declared in headers的实现的库。

分离的实现是人们想要的,当你不想与他人分享你的商业代码

所以,

 gcc -pthread test.c 

告诉gcclibpthread寻找在pthread.h中声明的定义。 -pthread被链接器自动扩展为libpthread

有/是编译器,你告诉它在lib目录是什么,它只是扫描所有希望找到匹配的文件。 那么有编译器是另一个极端,你必须告诉它的一切链接英寸这里的关键是包括只是告诉编译器寻找一些定义,甚至更简单的包括一些外部文件到这个文件。 这并不一定与图书馆或对象有任何联系,有许多包含这些东西并没有被束缚,这是一个坏的假设。 接下来链接器是一个不同的步骤,通常是与编译器不同的程序,所以不仅包含与对象或库没有一对一的关系,链接器也不是编译器。