stdio文件描述符(stdin,stdout,stderr)是否只能从#include'ing <stdio.h>打开?

时间:2017-11-27 10:57:13

标签: c linux

在将整数转换为C中的字符串时,我对包含stdio.h感到有些恼火 - 不会用不必要的文件描述符和其他代码来破坏二进制文件吗?或者只有在代码中使用标准的io文件描述符stdout,stdin或stderr时才会打开流,例如printfscanffprintf?如果我的代码只使用snprintf(3)

,也许还可以

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

bhuwansahni How to convert integer to string in C?中提供了一个很好的自助解决方案

我看不到如何使用(链接不起作用)itoa_itoa_fitoa_word,尽管_fitoa_word确实显示为nm /lib64/libc6.so.6的函数{1}}。

3 个答案:

答案 0 :(得分:5)

即使您不包含stdio.h,也会打开它们。它们是程序的标准流,并在运行时打开。

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

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

是的,如果你不使用它们就没问题。只使用像snprintf()这样的东西,你可以做得很好,但标准流仍然会被打开。使用它们与否并不重要。

谢谢 Paul Ogilvie

答案 1 :(得分:0)

  

我对包含stdio.h感到有些恼火 - 不会用不必要的文件描述符和其他代码来破坏二进制文件吗?

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

答案 2 :(得分:0)

实际上,在加载可执行文件之前,这些流甚至会打开。这就是通常发生的事情:

  • 有些shell会解析一个命令,告诉它执行你的程序。此命令可能包括stdinstdout和`stderr的重定向。

  • shell调用fork()来创建一个新进程。该新进程仍在运行shell代码。

  • 新进程中的shell代码按照已解析的重定向规定打开输入/输出流。如果你说2>/dev/null,它会打开/dev/null作为文件描述符2

  • 分叉的shell代码调用exec(),以控制代码。

  • 当您的代码写入stdout时,它只会写入已打开的文件描述符2

您可以看到,文件描述符012的解释只是将打开的文件描述符传递给进程的约定。您可以指示shell打开更多文件描述符5>myCoolStream,或关闭现有文件描述符。如果是这样,您的流程期望什么,那很好。如果您的流程需要其他内容,那就是您的问题。

因此,除了为<stdio.h>等提供通常的函数原型和类型定义之外,是否包含printf()没有任何效果。流本身完全不受此影响。