stdio文件描述符(stdin、stdout、stderr)是否仅从#include';ing<;stdio.h>;?

stdio文件描述符(stdin、stdout、stderr)是否仅从#include';ing<;stdio.h>;?,c,linux,C,Linux,在C语言中将整数转换为字符串时,我对包含stdio.h感到有点恼火——这会不会用不必要的文件描述符和其他代码填充二进制文件?或者,只有在代码中使用标准io文件描述符stdout、stdin或stderr时,才打开流,例如使用printf、scanf、fprintf?如果我的代码只使用snprintf(3),也许它仍然可以 我拥有的最接近的现成解决方案是将整数转换为strfromd(3)的双精度浮点,格式字符串不超过小数点 Bhuwanshani在年给出了一个很好的自己动手的解决方案 我不知道如何

在C语言中将整数转换为字符串时,我对包含
stdio.h
感到有点恼火——这会不会用不必要的文件描述符和其他代码填充二进制文件?或者,只有在代码中使用标准io文件描述符stdout、stdin或stderr时,才打开流,例如使用
printf
scanf
fprintf
?如果我的代码只使用
snprintf(3)
,也许它仍然可以

我拥有的最接近的现成解决方案是将整数转换为strfromd(3)的双精度浮点,格式字符串不超过小数点

Bhuwanshani在年给出了一个很好的自己动手的解决方案


我不知道如何使用(链接不起作用)
itoa
\u itoa
\u fitoa\u word
,尽管
\u fitoa\u word
确实显示为带有
nm/lib64/libc6的函数。因此,即使不包含
stdio.h
,它们也会被打开。它们是程序的标准流,在运行时已经打开

程序在实际执行之前需要一些初始化。这包括加载符号表、分配内存、初始化静态数据和链接动态库等。此时将打开标准流。然后该控件转到程序中的
main()
函数,并开始执行

对于第二个问题,标准IO不会使您的程序膨胀,因为您的程序几乎总是与标准C库
libc
链接,并且通常是动态链接的(因此不会增加可执行文件的大小)

是的,如果你不使用它们就好了。您只需使用
snprintf()
之类的东西就可以很好地完成这一切,但标准流仍将被打开。使用与否并不重要


感谢Paul Ogilvie

是否包含
stdio
头与这些文件描述符是否打开无关

这些是从操作系统(或shell)为您的程序打开的标准流,而不是由程序本身打开的。

否,这些文件不是通过包含头文件来“打开”的。包含头文件发生在编译时,即在运行时打开文件

在调用
main
函数之前,所有程序都需要进行一些初始化。这通常是由程序完成的,它不是真正从
main
函数开始,而是从编译器提供的另一段代码开始。此预主代码将执行程序正常运行所需的一些常规初始化,其中包括标准文件的设置

这些文件是如何创建的,以及它们是否引用了一些较低级别的文件句柄(例如POSIX系统上
标准输出的
FILENO\u STDOUT
文件描述符),这在很大程度上是无关紧要的。您需要知道的是,例如,
stdout
将在
main
函数中开始执行时存在

我对包含stdio.h有点恼火——这会不会用不必要的文件描述符和其他代码使二进制文件膨胀


不。链接C运行时会增加代码,但是如果没有它,您将无法完成很多工作。此运行时包含启动代码,可确保标准流可用。在许多系统上,新启动的进程已经从一开始就获得了各自打开的文件,可能是由父进程继承的。

在幕后处理文件、流和格式化输出的过程很多。是的,包括
,使用其中的例程会产生大量开销。但是,标准流是整个系统的一部分,它们一起运行。C库提供使用流的例程,操作系统提供访问文件系统的调用,命令行shell或其他进程在进程启动时提供已经打开的流,等等

对于正常流程,您可以忽略这一点。对于执行命令(由您直接键入或在shell脚本中键入),使命令正常工作所需的所有费用都很小。此外,您的可执行文件可以动态链接到标准库,而不是静态链接到标准库。这意味着库没有内置到可执行文件中。当您的程序运行时,它是可用的,但是它与系统中的其他进程共享,并且您的程序与它的连接不会产生额外的开销

如果您正在处理某些特殊进程或其他特殊软件,例如网络守护进程或设备驱动程序,那么有一些方法可以避免在标准C库或其部分中进行链接。但是,这些都是特定于平台的,您必须提供更多信息(可能在其他堆栈溢出问题中)来确切说明您正在尝试做什么以及您正在使用哪些平台(硬件、操作系统、开发人员工具)

开发特殊软件的一些工具包括精简的库,这些库提供简单的例程,而不需要很多开销


此外,C允许声明事物而不定义它们。
头声明了它需要的各种缓冲区和其他数据结构,但如果您不使用需要这些结构的流或其他功能,链接器可能不会从库中导入定义它们的模块,因此它们不会成为可执行文件的一部分。这方面的细节取决于C实现。

实际上,这些流在可执行文件加载之前就已经打开了。这就是通常发生的情况:

  • 一些shell解析命令,告诉它执行您的程序。此命令可能包括