C程序中包含headers时,linker/compiler如何找到对应的代码?
When including headers in a C program, how does the linker/compiler find the corresponding code?
我了解在创建 .c 和 .h 文件并将它们添加到我的项目时链接和编译的工作原理。
但是当我将 stdio.h 之类的 header 添加到我的项目时会发生什么?我知道链接器在某些标准目录中搜索 .h 文件,然后将其粘贴进去,但是 header 仅包含函数原型而没有代码。编译器或链接器在哪里找到这些函数的代码,它是如何添加到我的源文件中的?
我问的原因是因为我正在为微控制器编写引导加载程序,我想仔细查看实际发送到编译器的所有 C 代码。我正在为 PIC32 使用 non-optimized 免费版的 XC32 编译器,所以我不相信它只包括我实际使用的内容。
linker 根本不关心头文件。 linker 甚至不知道这些存在,因为它只看到已经编译的目标文件,这就是为什么您明确需要使用 -l...
选项指定要 link 反对的库。 linker 在标准 C 库 (-lc
) 中隐含地 links,这就是标准 C 函数的查找方式。在许多平台上,这不适用于 sin
或 pow
等数学函数,这就是为什么您需要 link 和 -lm
才能使用这些函数。
要回答指定给 link 与 -l...
对应的库在哪里的问题:编译器有一组标准目录供其查找。它可能还会查找工作目录。您可以使用 -L...
编译器选项将更多目录添加到 库搜索路径 。这告诉 linker 还要在指定的目录中查找库。
您需要区分 header 和库。
Headers 声明可供程序使用的设施。当您包含 header,例如 <stdio.h>
(注意:这是 not — 重复 not! — 一个库) ,您向编译器提供使用标准 I/O 库中的工具所需的信息。通常,C headers 不定义实现这些功能的实际代码。 C++ 有 'header only' 个库(Boost 的某些部分是 'header only' 个库的主要示例)。
图书馆提供设施的实施。 <stdio.h>
header 声明了一个函数fopen()
;某处有一个库定义了该函数。
一些headers(实际上,通常是很多headers)是有特权的,他们声明的设施包含在标准库中,C编译器links 你的程序。您无需执行任何特殊操作即可将函数 link 编辑到您的程序中。其他 header 来自 C 编译器事先不知道的库,对于那些,你必须告诉它在哪里可以找到库(例如,使用 -L /opt/sometool/lib
作为编译器选项)和图书馆名称(例如 -lsometool
,可能 link 与 /opt/sometool/lib/libsometool.so
或 /opt/sometool/lib/libsometool.a
)。请注意,SomeTool 的 header 可能在 /opt/sometool/include
中,您需要添加选项 -I/opt/sometool/include
才能找到 sometool.h
header.
linker 没有引用 headers;编译器本身不引用库。编译器控制程序确实处理混合(它通常将编译过程的多个阶段作为单独的程序运行——编译器与 linker 分开)。 headers 不包含有关库安装位置的信息。
我了解在创建 .c 和 .h 文件并将它们添加到我的项目时链接和编译的工作原理。
但是当我将 stdio.h 之类的 header 添加到我的项目时会发生什么?我知道链接器在某些标准目录中搜索 .h 文件,然后将其粘贴进去,但是 header 仅包含函数原型而没有代码。编译器或链接器在哪里找到这些函数的代码,它是如何添加到我的源文件中的?
我问的原因是因为我正在为微控制器编写引导加载程序,我想仔细查看实际发送到编译器的所有 C 代码。我正在为 PIC32 使用 non-optimized 免费版的 XC32 编译器,所以我不相信它只包括我实际使用的内容。
linker 根本不关心头文件。 linker 甚至不知道这些存在,因为它只看到已经编译的目标文件,这就是为什么您明确需要使用 -l...
选项指定要 link 反对的库。 linker 在标准 C 库 (-lc
) 中隐含地 links,这就是标准 C 函数的查找方式。在许多平台上,这不适用于 sin
或 pow
等数学函数,这就是为什么您需要 link 和 -lm
才能使用这些函数。
要回答指定给 link 与 -l...
对应的库在哪里的问题:编译器有一组标准目录供其查找。它可能还会查找工作目录。您可以使用 -L...
编译器选项将更多目录添加到 库搜索路径 。这告诉 linker 还要在指定的目录中查找库。
您需要区分 header 和库。
Headers 声明可供程序使用的设施。当您包含 header,例如 <stdio.h>
(注意:这是 not — 重复 not! — 一个库) ,您向编译器提供使用标准 I/O 库中的工具所需的信息。通常,C headers 不定义实现这些功能的实际代码。 C++ 有 'header only' 个库(Boost 的某些部分是 'header only' 个库的主要示例)。
图书馆提供设施的实施。 <stdio.h>
header 声明了一个函数fopen()
;某处有一个库定义了该函数。
一些headers(实际上,通常是很多headers)是有特权的,他们声明的设施包含在标准库中,C编译器links 你的程序。您无需执行任何特殊操作即可将函数 link 编辑到您的程序中。其他 header 来自 C 编译器事先不知道的库,对于那些,你必须告诉它在哪里可以找到库(例如,使用 -L /opt/sometool/lib
作为编译器选项)和图书馆名称(例如 -lsometool
,可能 link 与 /opt/sometool/lib/libsometool.so
或 /opt/sometool/lib/libsometool.a
)。请注意,SomeTool 的 header 可能在 /opt/sometool/include
中,您需要添加选项 -I/opt/sometool/include
才能找到 sometool.h
header.
linker 没有引用 headers;编译器本身不引用库。编译器控制程序确实处理混合(它通常将编译过程的多个阶段作为单独的程序运行——编译器与 linker 分开)。 headers 不包含有关库安装位置的信息。