链接和绑定之间的区别是什么

What is the difference between linking and binding?

本文关键字:区别 是什么 之间 绑定 链接      更新时间:2023-10-16

我读到关于这两件事的文章时感到困惑,两者之间有什么区别?

绑定是一个在多个上下文中使用的词。它总是与一件事与另一件事的联系有关,然而,当约束行为发生时,可能会有所不同。

有一个绑定时间的概念,或者某个组件绑定到另一个组件的点。绑定时间的基本列表是:(1)编译时的绑定,(2)链接时的绑定、(3)加载时的绑定和(4)运行时的绑定。

编译时绑定发生在编译源代码时。对于C/C++,有两个主要阶段,预处理器进行源文本替换,如定义替换或宏替换,以及编译源文本,将源文本转换为机器代码以及链接器的必要指令。

链接时绑定是指外部符号链接到一组特定的对象文件和库。您可能有几个不同的静态库,它们具有相同的一组函数名称,但函数的实际实现不同。因此,您可以通过选择不同的静态库来选择要使用的库实现。

加载时绑定是指加载程序将可执行文件与任何动态库或共享库一起加载到内存中。加载器将函数调用绑定到特定的动态库或共享库,所选的库可能会有所不同。

运行时绑定是指程序实际运行时,根据当前执行线程进行选择。

所以链接实际上只是绑定的一种类型。看看这个stackoverflow静态链接与动态链接,它提供了更多关于链接和库的信息。

您可能还对C++中的std::bind感兴趣,所以这里有一篇stackerflow文章std::function和std::bind,当它们应该被使用时,它们是什么。

在某个东西与其他东西绑定之前等待的时间越长,就可以在如何使用软件方面提供所需的灵活性。然而,延迟绑定和运行时效率以及源代码的复杂性之间往往存在权衡。

以绑定时间为例,考虑一个打开文件并读取文件然后关闭文件的应用程序。当文件名绑定到打开的文件时,可以选择几个不同的时间。

您可能会硬编码文件名,在编译时绑定,这意味着它只能与那一个文件一起使用。要更改文件名,必须更改源文件并重新编译。

用户可以输入文件名,例如通过用户提示或命令行参数,将文件名绑定到运行时打开的文件。要更改不再需要重新编译的文件名,只需使用不同的文件名再次运行程序即可。

假设您有一个声明为:的函数

void f(int, char);

以及:

void f(int);

用正确的签名调用函数f(4)。这就是绑定。链接器将链接到与签名void f(int)匹配的f的函数体的可用定义;

实际上,两者在c编程的上下文中具有相同的含义。有些人使用绑定,而另一些人则使用链接。

如果你想知道什么是链接,这里有一个简短的解释。

假设您创建了一个名为sum()的用户定义函数,其声明如下int sum(int,int);然后,无论何时从程序调用函数,程序都应该知道在内存中跳转到哪里来执行该函数。简单地说,程序应该知道被调用函数的地址,以便访问它的主体,这就是绑定。

现在sum是用户定义的函数,所以它将出现在源代码中。如果它是从main()调用的,那么它将在编译时链接到main,因为那个时候编译器将知道您的函数在可执行文件中的位置。这称为静态绑定。

现在想想printf(),它是库函数,它的主体不在程序中。所以当程序被编译时,printf的主体将不会出现在编译后的可执行文件中。当你执行程序时,它会被加载到内存中,它的地址在运行时是main已知的,而不是在编译时,因为它是sum()的情况。这种类型的链接称为动态链接。