【问题标题】:What is the difference between include and link when linking to a library?链接到库时包含和链接有什么区别?
【发布时间】:2014-10-25 12:24:26
【问题描述】:

包含和链接到底有什么作用?有什么区别?为什么我需要同时指定它们? 当我写#include math.h然后写-lm编译它,#include math.h和-lm分别是做什么的?

据我了解,在链接库时,您需要它的 .h 文件和它的 .o 文件。这是否暗示#include math.h 意味着接受.h 文件而-lm 接受.o 文件?

【问题讨论】:

  • 阅读Levine's book: Linkers and Loaders;你很困惑:头文件用于编译,目标文件用于链接。
  • c-faq 中提供了简短说明。 “在外部库中调用代码的一般情况下,使用#include 拉入正确的头文件只是故事的一半;您还必须告诉链接器搜索外部库本身。头文件只告诉编译器如何调用外部函数;头文件不提供外部函数的定义,或者告诉编译器/链接器在哪里可以找到这些定义。"
  • 谢谢,Basile Starynkevitch 和 remyabel !!我发现这两个来源都非常有帮助!
  • #include ... 处理文本,源代码;链接 (-l...) 处理目标代码(二进制编译语句)。

标签: c linker


【解决方案1】:

同时需要标头(接口描述)和库(实现)的原因是,C 比 C# 或 Java 等语言更清楚地将两者分开。可以编译一个 C 函数(例如通过调用 gcc -c <sourcefile>),即使被调用的库不存在,它也会调用库代码;包含接口描述的标头就足够了。 (这对于 C# 或 Java 是不可能的;必须存在程序集和类文件/jar。)在 link 阶段,尽管库必须存在,即使它是动态的,afaik。

相比之下,对于 C#、Java 或脚本语言,实现包含定义接口所需的所有信息。编译器(与链接器没有明显分离)查看包含调用实现的 jar 文件或 C# 程序集,并从那里获取有关函数签名和类型的信息。

理论上,这些信息也可能存在于用 C 编写的库中——它基本上是调试信息。但是经典的 C 编译器(与链接器相反)忽略了库或目标文件,并且无法解析它们。 (应该记住,您通常用于编译 C 程序的“编译器”可执行文件,例如 gcc,是一个“编译器驱动程序”,它解释命令行参数并调用实际执行操作的程序,例如预处理器、实际编译器和实际的链接器,以创建所需的输出。)

所以理论上,如果您在已知位置有一个正确注释的库,您可能会编写一个编译器来针对它编译一个 C 函数,而无需函数声明和类型定义;编译器必须产生正确的声明。编译器必须知道要解析哪个库(对应于在 VS 中设置 C# 项目“引用”或在 Java 中具有类路径和名称/类对应关系)。

使用众所周知的调试格式(如 stabs 或 dwarf)并使用一个小帮助程序从中提取接口定义可能是最简单的,该程序使用调试格式的 API,提取信息并生成一个 C 头文件附加到每个源文件中。那将是编译器驱动程序的工作,而实际的编译器仍然不会注意到这一点。

【讨论】:

    【解决方案2】:

    这是因为头文件只包含声明,而.o 文件(或 .obj、.dll 或 .lib)包含方法的定义。 如果你打开一个.h 文件,你将看不到方法的代码,因为它在库中。 一个原因是商业性的,因为您需要发布您的代码并在您的公司拥有源代码。库已编译,因此您可以发布它。 头文件只告诉编译器,它可以在库中找到哪些类和方法。

    【讨论】:

      【解决方案3】:

      头文件是一种目录加上一种编译器的字典。它告诉编译器库提供什么,并给出特殊值可读的名称。

      库文件本身包含内容。

      【讨论】:

        【解决方案4】:

        你问的是完全不同的两件事。 别担心,我会向你解释的。 您使用 # 符号指示预处理器包含内部包含 fabs()、ceil() 等函数原型的 math.h 头文件。 并且您使用 -lm 来指示链接器,将 fabs()、ceil() 等函数的预编译函数定义包含在 exe 文件中。 现在,您可能会问为什么我们必须显式链接数学函数的库文件,而不是其他函数,答案是,这是由于一些未定义的历史原因。

        【讨论】:

          猜你喜欢
          • 2014-11-26
          • 1970-01-01
          • 2010-09-16
          • 2010-12-26
          • 1970-01-01
          • 2014-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多