C 运行时库第 2 部分

B.G*_*ill 5 c runtime

当我对旧的问题有一些进一步的问题时,有人建议我创建新的问题并参考旧的问题。所以,这就是最初的问题:什么是 C 运行时库?

好的,根据您的回答,我现在知道静态链接库是 Microsoft 对 C 标准函数的实现。现在:

如果我做对了,方案如下:我想使用 printf(),所以我必须包括<stdio.h>它只是告诉编译器有一个带有这些参数的函数 printf()。现在,当我编译代码时,因为 printf() 是在 C 标准库中定义的,并且因为 Microsoft 决定将其命名为 C 运行时库,所以它会自动从 libcmt.lib(如果 libcmt.lib 在编译器中设置)静态链接编译时间。我问,因为在维基百科上,在关于运行时库的文章中,运行时库是在运行时链接的,但是 .lib 文件是在编译时链接的,对吗?

现在,让我困惑的是什么。有 C 标准库的 .dll 版本。但我认为要链接 .dll 文件,您必须实际调用 winapi 程序来加载该库。那么,如果没有静态库提供代码来告诉 Windows 从 dll 加载所需的函数,如何动态链接这些函数?

关于这个主题的最后一个问题 - C 标准库函数是否也会调用 winapi,即使它们不是更高级的 WinAPI 函数那样的 .dll 文件?我的意思是,最终要访问帧缓冲区并打印某些内容,您必须告诉 Windows 这样做,因为操作系统不能让您直接操作硬件。我认为它就像必须编写操作系统以在类似版本中以相同的方式支持所有 C 标准库函数,因为它们是静态链接的,并且可以不同地支持更复杂的 WinAPI 调用,因为新版本的操作系统可以在 .dll 文件中进行调整.

Pin*_*juh 2

C 运行时中的链接是“主”函数的包装器;它会初始化运行 C 代码之前所需的一切。它不包含任何“函数”,这些函数位于 C 标准库(动态链接)中。

我认为您误解了动态链接:它是由操作系统完成的。因此,您告诉操作系统您的可执行文件需要 DLL ab和. 当您执行可执行文件时,操作系统会将可执行文件加载到内存位置,并在可执行文件中读取运行它所需的内容。然后它会抓取这些 DLL 并将它们粘贴到可执行文件的内存区域中,然后它会告诉您的代码加载于、加载于等等,以便您的代码可以调用它的函数。cdaxby

有时,编译器在编译时包含(称为静态链接)一个库:它们这样做,这样操作系统就不必在运行时加载它,因此加载速度更快。

.lib文件是不带“D”的 DLL 文件,因为它们可以静态链接。还可以动态链接库文件;这会使您的可执行文件更小,但会使可执行文件的加载时间更慢。

关于 WinAPI:大多数对 C 库的调用都会转换为(部分)对 WinAPI 的调用;但前提是它们必须与操作系统交互(I/O 等)。不同之处在于,C 库在大多数平台上都是相同的,因此如果您使用 C 库而不是直接使用 Windows API,则会增加可移植性。

更新

您问如果完全动态链接可执行文件如何加载 DLL?好吧:你不必!“加载 dll”和“调用加载 dll”之间的区别是;当您启动应用程序时,“加载 dll”由操作系统完成。操作系统将在您的可执行文件中搜索特定的“导入表”。它是一个表格,说明在执行之前(即在Windows 上)它真正需要哪些 DLL 。操作系统甚至会在代码运行之前进行“调用加载 dll”。kernel32.dlluser32.dll

“调用加载 dll”也存在于kernel32.dll您的代码中被调用:可以在您的代码运行时加载/卸载 DLL。如果您有一个巨大的代码库,并且您希望在整个应用程序生命周期(例如在启动期间)卸载一次性使用的库来释放内存,那么这可能是一种情况。如果不再使用该函数,可以卸载该 DLL。但也有可能您需要一些尚未加载的功能来加快加载速度。如果您自己需要该函数,则可以加载 DLL。这是相当高级的东西,大多数时候,操作系统无论如何都会交换掉未使用的 DLL(“删除”内存,字面意思是:它将不常用的内存(如未使用的 DLL)移动到一个大的地方存储,如硬盘。如果您需要它,它会自动将其“交换”回来!)。

所以:您不必太关心 Windows 上加载/卸载 DLL 的问题。如果您有一个好的链接器,并告诉它动态链接库,那么一切都会很好。