为什么当 #include 形式的信息已经存在于源文件中时,我们必须告诉 gcc 链接哪个库?
例如,如果我有一个使用线程的代码并且有:
#include <pthread.h>
我仍然需要在 gcc 中使用 -pthread 选项进行编译:
gcc -pthread test.c
如果我不提供 -pthread 选项,则会在找到线程函数定义时出错。
我正在使用这个版本:
gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
答案 0 :(得分:4)
这可能是让初学者走向C的最常见的事情之一。
在C中,有两个不同的步骤来构建程序,编译和链接。出于您的问题的目的,这些步骤将您的代码连接到两种不同类型的文件,标题和库。
C代码中的hive -S -e "SHOW COLUMNS IN database_name.table_name" > column_names.txt
指令由编译器处理。在将C文件转换为目标文件之前,编译器(实际上是预处理器)将#include <pthread.h>
的内容字面粘贴到您的代码中。
pthread.h
是头文件,而不是库。它包含了您可以在库中找到的函数列表,它们采用的参数以及它们返回的内容。标头可以在没有库的情况下存在,反之亦然。标题是一个文本文件,通常在Unix派生系统的pthread.h
中找到。你可以像任何C文件一样打开它来阅读内容。
命令行/usr/include
同时进行编译和链接。在过去,您首先会执行gcc -lpthread test.c
,然后cc test.c
之类的操作。如您所见,ld -lpthread test.o
实际上是链接器的一个选项。
链接器对C代码或标题等文本文件一无所知。它仅适用于编译的目标文件和现有的库。 -lpthread
标志告诉它查找哪些库以查找您正在使用的函数。
答案 1 :(得分:3)
标题的名称与库的名称无关。这真的只是出乎意外。通常,图书馆提供了许多标题。
特别是在C ++中,每个类通常有一个标头,并且该库通常提供来自同一名称空间的类实现。在C中,标题被组织为包含一些共同的函数子集 - stdio.h
包含数学运算,Random ran = new Random();
int x = ran.nextInt(eMinor.size() - 1)
System.out.println(eMinor.get(x));
提供IO函数等。
答案 2 :(得分:2)
它们是两个不同的东西。 .h文件包含声明,有时也包含内联函数。众所周知,每个函数都应该有一个实现/定义才能工作。这些实现是分开保存的。 pwd
例如是以二进制形式保存-lpthread
实现的库。
当您不想与他人分享您的商业代码时,将实施分离是人们想要的
所以,
functions declared in headers
告诉gcc -pthread test.c
查找gcc
中pthread.h
中声明的定义。 libpthread
被链接器自动扩展为-pthread
答案 3 :(得分:1)
有一些编译器,你告诉它lib目录的位置,它只是扫描了所有想要找到匹配的文件。然后有一些编译器是另一个极端,你必须告诉它要链接的所有东西。这里的关键是简单地告诉编译器寻找一些定义,甚至更简单地将一些外部文件包含到这个文件中。这不一定与库或对象有任何连接,有许多包含与这些东西无关,这是一个不好的假设。接下来链接器是一个不同的步骤,通常是与编译器不同的程序,因此包含不仅与对象或库没有一对一的关系,链接器也不是编译器。