- 1)预处理器,链接器,2)头文件,库有什么区别?我的理解正确吗? [英] What is the difference between - 1) Preprocessor,linker, 2)Header file,library? Is my understanding correct?

查看:10
本文介绍了- 1)预处理器,链接器,2)头文件,库有什么区别?我的理解正确吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,直到今天早上我都对这些术语感到困惑.我想我已经有所不同了,希望如此.

Okay, until this morning I was thoroughly confused between these terms. I guess I have got the difference, hopefully.

首先,令人困惑的是,由于预处理器已经将头文件包含在包含函数的代码中,链接器将哪些库函数链接到汇编器/编译器生成的目标文件?部分混淆主要是由于我对头文件和库之间的区别一无所知.

Firstly, the confusion was that since the preprocessor already includes the header files into the code which contains the functions, what library functions does linker link to the object file produced by the assembler/compiler? Part of the confusion primarily arose due to my ignorance about the difference between a header file and a library.

经过一番谷歌搜索和堆栈溢出(这是术语吗?:p),我收集到头文件主要包含函数声明,而实际实现在另一个名为库的二进制文件中(我仍然不是 100% 确定这一点).

After a bit of googling, and stack-overflowing (is that the term? :p), I gathered that the header file mostly contains the function declarations whereas the actual implementation is in another binary file called the library (I am still not 100% sure about this).

所以,假设在以下程序中:-

So, suppose in the following program:-

#include<stdio.h>
int main()
{
      printf("whatever");
      return 0;
}

预处理器将头文件的内容包含在代码中.编译器/编译器+汇编器完成它的工作,最后链接器将这个目标文件与另一个实际存储 printf() 工作方式的目标文件结合起来.

The preprocessor includes the contents of the header file in the code. The compiler/compiler+assembler does its work, and then finally linker combines this object file with another object file which actually has stored the way printf() works.

我的理解正确吗?我可能会走得很远......所以你能帮帮我吗?

Am I correct in my understanding? I may be way off...so could you please help me?

我一直想知道 C++ STL.它总是让我困惑它到底是什么,所有这些标题的集合还是什么?现在阅读回复后,我可以说 STL 是一个目标文件/类似于目标文件的东西吗?

I have always wondered about the C++ STL. It always confused me as to what it exactly is, a collection of all those headers or what? Now after reading the responses, can I say that STL is an object file/something that resembles an object file?

而且,我想我可以在哪里读取函数的函数定义,如 pow()sqrt() 等.我会打开头文件而不是找到任何东西.那么,库中的函数定义是不是二进制不可读的形式呢?

And also, I thought where I could read the function definitions of functions like pow(), sqrt() etc etc. I would open the header files and not find anything. So, is the function definition in the library in binary unreadable form?

推荐答案

AC 源文件经过两个主要阶段,(1) C 源代码由预处理器实用程序处理的预处理器阶段,它查找预处理器指令并执行那些动作和 (2) 编译阶段,处理过的 C 源代码随后被实际编译以生成目标代码文件.

A C source file goes through two main stages, (1) the preprocessor stage where the C source code is processed by the preprocessor utility which looks for preprocessor directives and performs those actions and (2) the compilation stage where the processed C source code is then actually compiled to produce object code files.

预处理器是一个进行文本操作的实用程序.它将包含可能包含预处理器指令的文本(通常是 C 源代码)的文件作为输入,并通过将找到的任何指令应用于文本输入以生成文本输出来输出文件的修改版本.

The preprocessor is a utility that does text manipulation. It takes as input a file that contains text (usually C source code) that may contain preprocessor directives and outputs a modified version of the file by applying any directives found to the text input to generate a text output.

该文件不必是 C 源代码,因为预处理器正在处理文本.我已经看到 C Preprocssor 用于通过允许将 preprossor 指令包含在 make 文件中来扩展 make 实用程序.带有 C Preprocessor 指令的 make 文件通过 C Preprocessor 实用程序运行,然后将生成的输出馈送到 make 以执行 make 目标的实际构建.

The file does not have to be C source code because the preprocessor is doing text manipulation. I have seen the C Preprocssor used to extend the make utility by allowing preprossor directives to be included in a make file. The make file with the C Preprocessor directives is run through the C Preprocessor utility and the resulting output then fed into make to do the actual build of the make target.

库和链接

库是包含各种功能的目标代码的文件.这是一种在将多个源文件编译成单个文件时将其输出打包的方法.很多时候,库文件与头文件(包含文件)一起提供,通常带有 .h 文件扩展名.头文件包含函数声明、全局变量声明以及库所需的预处理器指令.因此,要使用该库,您需要包含使用 #include 指令提供的头文件,然后链接到该库文件.

A library is a file that contains object code of various functions. It is a way to package the output from several source files when they are compiled into a single file. Many times a library file is provided along with a header file (include file), typically with a .h file extension. The header file contains the function declarations, global variable declarations, as well as preprocessor directives needed for the library. So to use the library, you include the header file provided using the #include directive and you link with the library file.

库文件的一个很好的特性是您提供的是源代码的编译版本,而不是源代码本身.另一方面,由于库文件包含已编译的源代码,因此用于生成库文件的编译器必须与用于编译您自己的源代码文件的编译器兼容.

A nice feature of a library file is that you are providing the compiled version of your source code and not the source code itself. On the other hand since the library file contains compiled source code, the compiler used to generate the library file must be compatible with the compiler being used to compile your own source code files.

常用的库有两种.第一种和较旧的类型是静态库.第二个也是最近的动态库(Windows 中的动态链接库或 DLL 和 Linux 中的共享库或 SO).两者的区别在于库中的函数绑定到使用库文件的可执行文件时.

There are two types of libraries commonly used. The first and older type is the static library. The second and more recent is the dynamic library (Dynamic Link Library or DLL in Windows and Shared Library or SO in Linux). The difference between the two is when the functions in the library are bound to the executable that is using the library file.

链接器是一个实用程序,它使用各种目标文件和库文件来创建可执行文件.当在 C 源文件中使用外部或全局函数或变量时,会使用一种标记告诉链接器需要在该点插入函数或变量的地址.

The linker is a utility that takes the various object files and library files to create the executable file. When an external or global function or variable is used the C source file, a kind of marker is used to tell the linker that the address of the function or variable needs to be inserted at that point.

C 编译器只知道它编译的源代码中的内容,而不知道其他文件(例如目标文件或库)中的内容.所以链接器的工作是获取各种目标文件和库,并通过用实际连接替换标记来建立部件之间的最终连接.因此,链接器是将各种组件链接"在一起的实用程序,将目标文件和库中的全局函数或变量的标记替换为指向为该全局函数或变量生成的实际目标代码的链接.

The C compiler only knows what is in the source it compiles and does not know what is in other files such as object files or libraries. So the linker's job is to take the various object files and libraries and to make the final connections between parts by replacing the markers with actual connections. So a linker is a utility that "links" together the various components, replacing the marker for a global function or variable in the object files and libraries with a link to the actual object code that was generated for that global function or variable.

在链接器阶段,静态库与动态或共享库之间的区别变得明显.当使用静态库时,库的实际目标代码包含在应用程序可执行文件中.当使用动态或共享库时,应用程序可执行文件中包含的目标代码是在应用程序运行时找到共享库并与之连接的代码.

During the linker stage is when the difference between a static library and a dynamic or shared library becomes evident. When a static library is used, the actual object code of the library is included in the application executable. When a dynamic or shared library is used, the object code included in the application executable is code to find the shared library and connect with it when the application is run.

在某些情况下,相同的全局函数名称可能会在几个不同的目标文件或库中使用,因此链接器通常只会使用它遇到的第一个并发出警告,发现其他文件或库.

In some cases the same global function name may be used in several different object files or libraries so the linker will normally just use the first one it comes across and issue a warning about others found.

编译链接总结

所以一个C程序的编译和链接的基本过程是:

So the basic process for a compile and link of a C program is:

  • 预处理器实用程序生成要编译的 C 源代码

  • preprocessor utility generates the C source to be compiled

编译器将 C 源代码编译成目标代码,生成一组目标文件

compiler compiles the C source into object code generating a set of object files

链接器将各种目标文件以及任何库链接到可执行文件中

linker links the various object files along with any libraries into executable file

以上是基本过程,但是当使用动态库时,它可能会变得更加复杂,尤其是如果正在生成的应用程序的一部分具有它正在生成的动态库.

The above is the basic process however when using dynamic libraries it can get more complicated especially if part of the application being generated has dynamic libraries that it is generating.

加载器

还有应用程序实际加载到内存并开始执行的阶段.操作系统提供了一个实用程序,加载程序,它读取应用程序可执行文件并将其加载到内存中,然后启动应用程序运行.可执行文件的起始点或入口点在可执行文件中指定,因此在加载程序将可执行文件读入内存后,它将通过跳转到入口点内存地址来启动可执行文件.

There is also the stage of when the application is actually loaded into memory and execution starts. An operating system provides a utility, the loader, which reads the application executable file and loads it into memory and then starts the application running. The starting point or entry point for the executable is specified in the executable file so after the loader reads the executable file into memory it will then start the executable running by jumping to the entry point memory address.

链接器可能遇到的一个问题是,有时它在处理需要实际内存地址的目标代码文件时可能会遇到标记.但是,链接器不知道实际的内存地址,因为地址会根据应用程序在内存中的加载位置而有所不同.因此,链接器将其标记为加载程序实用程序在加载程序将可执行文件加载到内存并准备开始运行时修复的问题.

One problem the linker can run into is that sometimes it may come across a marker when it is processing the object code files that requires an actual memory address. However the linker does not know the actual memory address because the address will vary depending on where in memory the application is loaded. So the linker marks that as something for the loader utility to fix when the loader is loading the executable into memory and getting ready to start it running.

在现代 CPU 具有硬件支持的虚拟地址到物理地址映射或转换的情况下,实际内存地址的问题很少成为问题.每个应用程序都加载到相同的虚拟地址,硬件地址转换处理实际的物理地址.然而,较旧的 CPU 或成本较低的 CPU,例如缺乏内存管理单元 (MMU) 硬件支持地址转换的微控制器,仍然需要解决这个问题.

With modern CPUs with hardware supported virtual address to physical address mapping or translation, this issue of actual memory address is seldom a problem. Each application is loaded at the same virtual address and the hardware address translation deals with the actual, physical address. However older CPUs or lower cost CPUs such as micro-controllers that are lacking the memory management unit (MMU) hardware support for address translation still need this issue addressed.

入口点和 C 运行时

最后一个主题是 C 运行时和 main() 以及可执行入口点.

A final topic is the C Runtime and the main() and the executable entry point.

C 运行时是编译器制造商提供的目标代码,其中包含用 C 编写的应用程序的入口点.main() 函数是编写程序的程序员提供的入口点应用程序但是这不是加载程序看到的入口点.main() 函数在应用程序启动后由 C Runtime 调用,C Runtime 代码为应用程序设置环境.

The C Runtime is object code provided by the compiler manufacturer that contains the entry point for an application that is written in C. The main() function is the entry point provided by the programmer writing the application however this is not the entry point that the loader sees. The main() function is called by the C Runtime after the application is started and the C Runtime code sets up the environment for the application.

C 运行时不是标准 C 库.C 运行时的目的是管理应用程序的运行时环境.标准 C 库的目的是提供一组有用的实用函数,以便程序员不必创建自己的函数.

The C Runtime is not the Standard C Library. The purpose of the C Runtime is to manage the runtime environment for the application. The purpose of the Standard C Library is to provide a set of useful utility functions so that a programmer doesn't have to create their own.

当加载程序加载应用程序并跳转到 C 运行时提供的入口点时,C 运行时会执行各种初始化操作,为应用程序提供适当的运行时环境.完成后,C 运行时调用 main() 函数,以便应用程序开发人员或程序员创建的代码开始运行.当 main() 返回或调用 exit() 函数时,C 运行时执行清理和关闭应用程序所需的任何操作.

When the loader loads the application and jumps to the entry point provided by the C Runtime, the C Runtime then performs the various initialization actions needed to provide the proper runtime environment for the application. Once this is done, the C Runtime then calls the main() function so that the code created by the application developer or programmer starts to run. When the main() returns or when the exit() function is called, the C Runtime performs any actions needed to clean up and close out the application.

这篇关于- 1)预处理器,链接器,2)头文件,库有什么区别?我的理解正确吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆