前言
stdio.h 是我们经常使用的一个标准库。基本上现在的C编辑器都自动会在C文件中添加这个头文件。这一篇博客主要就是来了解这个库的前世今生。
——star
stdio.h是什么?
这个头文件声明了很多的输入输出函数。当然几乎所有的用户级别程序都需要输入输出,事实上这也是C标准库出现的最早的头文件之一。并且它也是包含所有最多函数的头文件。所以相信探秘它也是需要很多的笔墨与精力。
最早的IO函数出现在上个世纪60年代,不过那个时候的输入输出程序的可移植性几乎没有,这一直也是那个时代计算机需要解决的问题,后来FORTRAN提出了一个思路就是编写更多的独立的输入输出函数。自此独立于设备的IO时代降临了。
后来70年代的早期UNIX诞生了,它将所有的文本流都采用了标准的内部形式,每一行以一个换行符来终止。
后来就有了ioctl,通过一种映射的机制控制文本处理设备。另一个修正文本流的方式是直接通过该设备的专门软件。对于每一个可能用到的设备来说,用户必须添加一个常驻系统的设备管理程序,这个东西让我想到了中断线相关的东西,就好比每一个设备都需要一个对应与自己的中断处理程序,这也是现代操作系统的一个设备管理方式吧。
再后来文件描述符诞生了,并且每一个运行的程序支持三个标准的文件描述符,标准输入,标准输出,标准错误。
但是我们每次打开一个文件都不可能选用函数IOCTL它需要指定一堆的参数,所以应当写一个标准库来封装这个函数。达到简单操作的目的。
文本行的长度:
有一些系统甚至不能表示空文本行,因此输出空文本行的时候,库实际上输出的可能就是包含一个空格的文本行,在读取的时候系统就会自动去掉只有一个空格的文本行。还有一些只能读取固定长度的文本行,但是明显这都是在早期的问题现在基本都已经解决了这个问题。
文件的长度:
某些系统不能表示空文件,如果创建了一个新文件但是没有写如任何都系,在关闭的时候,很有可能C标准会删除这个文件,因为在C标准看来一个空的文件没有什么用。
最终的结果:
如果使用UNIX的原语性能会收到影响,还有如果持续在用户空间创建缓冲区明显也不是一个明智之举。有些IO程序就开始不使用UNIX原语,但是站在标准的角度来看我们可能为了解决一个问题而产生多个处理程序,所以最终还是规定使用流,添加FILE类型来处理问题。也就是我们现在使用的fopen 函数族。
C标准的内容:
<STDIO.H>总共定义了三种类型,一些宏和很多的执行输入数出的函数。
声明的类型:
size_t , FILE ,fpos_t 简要说一下最后一个类型:这是一个对象类型,可以指定唯一的文件的每一个位置所需要的信息。
声明的宏:
_IOFBF
_IOLBF
_IONBF
这个三个宏是setvbuf 的三个参数使用。
BUFSIZ
这个宏是指setbuf 函数所指的缓冲区大小
EOF
文件爱你描述符,很常见。
FOPEN_MAX
一个应用中可以同时打开的所有文件描述符数量。
FILENAME_MAX
一个文件名的最长大小,注意这里是使用char 数组存储的函数名。
L_tmpnam,TMP_MAX。
表示使用tmpnam.最大生成文件名,以及长度。
SEEK_CUR,SEEK_END,SEEK_SET 不多说很熟悉fseek函数的三个参数,用来设置文件指针的位置状态。
stderr,stdin,stdout 指向 FILE的类型指针。
环境限制:
实现支持的文本文件的每一行应该至少可以包含254个字符,包括结束的换行符。宏的BUFSIZE的值至少应该为256.
每个程序开始后其实已经打开了三个标准流,所以宏 FOPEN_MAX至少是3.
定义的函数:(这里直说很少用到的函数,常用的包括LINUXC不再说明范围内,因为已经很熟了)
remove.
rename.
tmpfile.
FILE *tmpfile(void)
这个函数创建一个临时二进制文件,当这个文件关闭程序或者终止的时候,它会被自动的删除。如果程序异常终止,打开的文件是否会删除这是根据实现决定的,这个文件打开时通过模式“wb+"进行更新。
返回值是创建的文件的流指针,如果不能创建,函数返回一个空指针。
查看原文:http://zmrlinux.com/2015/11/24/%e6%8e%a2%e7%a7%98-stdio-h/