C是否有类似"from-import"的机制?
Does C has a "from-import"-like mechanism?
我已阅读 here 关于在 python 中导入模块的内容。可以选择不导入整个模块(例如 sys),只导入其中的一部分(例如 sys.argv)。这在 C 中可能吗?我可以只包含 printf 或任何其他函数的实现而不是整个 stdio.h 库吗?
我问这个是因为在我只需要几行代码的地方包含整个文件似乎效率很低。
我知道仅包含函数本身可能不起作用,因为它依赖于其他函数、其他包含、定义和全局变量。我只是为了将它用于包含执行所需的所有数据的整个代码块而询问。
C 没有任何等同于甚至类似于 Python 的 "from ... import" 机制的东西。
I ask this because it seems very inefficient to include a whole file where I need only several lines of code.
实际上,当您 #include
一个文件时,通常 发生的是导入宏声明或在其他地方声明的函数。您不导入任何可执行代码...因此 "unnecessary" 包含对运行时代码大小或效率的影响为零。
如果您使用(即"call")宏,则会导致宏主体扩展,从而增加可执行代码的大小。
如果您调用一个函数,其声明包含在内,那将为调用语句本身添加代码...。虽然功能没有扩展。相反,一个 "external reference" 被添加到您的“.o”文件,当您从“.o”文件和依赖库创建可执行文件时,加载程序会解析它。
Python:“有一个选项可以不导入整个模块”:我想你误解了什么是在这里进行。当您指定要导入的名称时,这意味着只有那些 names 进入您的名称空间。 "whole" 模块已编译,函数外的任何代码都是 运行,即使您只指定一个名称也是如此。
C:我将假设您正在使用像 UNIX/Linux/OS X 或 Windows 这样的操作系统(以下不适用于嵌入式系统)。
最接近 import
的 C 是动态 运行时间链接。那不是标准C的一部分,它是由操作系统定义的。所以 POSIX 有一种机制而 Windows 有另一种机制。大多数人称这些库文件为 "DLLs",但严格来说这是 Microsoft 的术语,它们在 UNIX 类型系统上是 "shared objects" (.so)。
当进程附加到 DLL 或 .so 时,它会 "mapped" 进入进程的虚拟内存。此处的详细信息因操作系统而异,但本质上代码分为 "pages",其大小各不相同,但 32 位系统为 4kb,64 位系统为 16kb 是典型的。只有那些需要的页面才会加载到内存中。当需要页面时,会发生所谓的 "page-fault",操作系统将从可执行文件或交换区域(取决于 OS)获取页面。
这种机制的优点之一是代码页可以在进程之间共享。因此,如果您有 50 个进程都使用相同的 DLL(例如 C 运行-time 库),那么实际上只有 一个 副本被加载到内存中。它们都共享一组页面(它们可以共享,因为它们是只读的)。
没有像 Python 那样的共享机制 - 除非模块本身是用 C 编写的并且是一个 DLL (.pyd)。
所有这些都是在程序不知情的情况下发生的。
编辑:看看其他人的回答,我意识到您可能正在考虑使用 #include
预处理器指令将头文件合并到源代码中。假设这些是标准头文件,那么它们对您的可执行文件的大小没有影响,它们应该是“idempotent”。也就是说,它们只包含预处理器、编译器或链接器使用的信息。如果头文件中有未使用的定义,则应该没有副作用。
链接未使用的库(-l 指令到编译器)将使可执行文件更大,从而使页表更大,但除此之外,如果它们未被使用,则它们不应该有任何显着差异.那是因为上面描述的按需页面加载(这个概念是 1960 年代在英国曼彻斯特发明的)。
我已阅读 here 关于在 python 中导入模块的内容。可以选择不导入整个模块(例如 sys),只导入其中的一部分(例如 sys.argv)。这在 C 中可能吗?我可以只包含 printf 或任何其他函数的实现而不是整个 stdio.h 库吗?
我问这个是因为在我只需要几行代码的地方包含整个文件似乎效率很低。
我知道仅包含函数本身可能不起作用,因为它依赖于其他函数、其他包含、定义和全局变量。我只是为了将它用于包含执行所需的所有数据的整个代码块而询问。
C 没有任何等同于甚至类似于 Python 的 "from ... import" 机制的东西。
I ask this because it seems very inefficient to include a whole file where I need only several lines of code.
实际上,当您 #include
一个文件时,通常 发生的是导入宏声明或在其他地方声明的函数。您不导入任何可执行代码...因此 "unnecessary" 包含对运行时代码大小或效率的影响为零。
如果您使用(即"call")宏,则会导致宏主体扩展,从而增加可执行代码的大小。
如果您调用一个函数,其声明包含在内,那将为调用语句本身添加代码...。虽然功能没有扩展。相反,一个 "external reference" 被添加到您的“.o”文件,当您从“.o”文件和依赖库创建可执行文件时,加载程序会解析它。
Python:“有一个选项可以不导入整个模块”:我想你误解了什么是在这里进行。当您指定要导入的名称时,这意味着只有那些 names 进入您的名称空间。 "whole" 模块已编译,函数外的任何代码都是 运行,即使您只指定一个名称也是如此。
C:我将假设您正在使用像 UNIX/Linux/OS X 或 Windows 这样的操作系统(以下不适用于嵌入式系统)。
最接近 import
的 C 是动态 运行时间链接。那不是标准C的一部分,它是由操作系统定义的。所以 POSIX 有一种机制而 Windows 有另一种机制。大多数人称这些库文件为 "DLLs",但严格来说这是 Microsoft 的术语,它们在 UNIX 类型系统上是 "shared objects" (.so)。
当进程附加到 DLL 或 .so 时,它会 "mapped" 进入进程的虚拟内存。此处的详细信息因操作系统而异,但本质上代码分为 "pages",其大小各不相同,但 32 位系统为 4kb,64 位系统为 16kb 是典型的。只有那些需要的页面才会加载到内存中。当需要页面时,会发生所谓的 "page-fault",操作系统将从可执行文件或交换区域(取决于 OS)获取页面。
这种机制的优点之一是代码页可以在进程之间共享。因此,如果您有 50 个进程都使用相同的 DLL(例如 C 运行-time 库),那么实际上只有 一个 副本被加载到内存中。它们都共享一组页面(它们可以共享,因为它们是只读的)。
没有像 Python 那样的共享机制 - 除非模块本身是用 C 编写的并且是一个 DLL (.pyd)。
所有这些都是在程序不知情的情况下发生的。
编辑:看看其他人的回答,我意识到您可能正在考虑使用 #include
预处理器指令将头文件合并到源代码中。假设这些是标准头文件,那么它们对您的可执行文件的大小没有影响,它们应该是“idempotent”。也就是说,它们只包含预处理器、编译器或链接器使用的信息。如果头文件中有未使用的定义,则应该没有副作用。
链接未使用的库(-l 指令到编译器)将使可执行文件更大,从而使页表更大,但除此之外,如果它们未被使用,则它们不应该有任何显着差异.那是因为上面描述的按需页面加载(这个概念是 1960 年代在英国曼彻斯特发明的)。