为了implement freopen(),我提出了标准中的一项规范,据我所知,它实际上并未指定任何内容。
So ... freopen()
将关闭流(忽略错误),清除其错误和EOF标志,重置宽方向,然后以给定模式重新打开流。这很清楚;这基本上是一个fclose()/ fopen()。即使未采用这种方式定义,也很清楚这是预期的。
但是,关于setvbuf()
可能对流所做的事情,我有两个问题-设置用户分配的缓冲区和/或更改缓冲区策略。
问题1。
1]是否期望freopen()
将其恢复为默认状态,就像它实际上已调用了fopen()
一样?还是无论用户通过旧setvbuf()
设置的内容,它都有望延续到新的流中?这涉及缓冲存储器和缓冲策略,但是这里的主要问题是缓冲存储器。
fclose()
的规范指定用户通过setvbuf()
与流相关联的任何缓冲区都已取消关联,即,用户现在可以将其free()
设置为对象。
但是freopen()
仅指定它关闭与流相关联的文件,而不是fclose()
使用它。
因此,在freopen()
之后,用户关联的缓冲存储器是否仍与该流关联?
问题2。
freopen()
可以想象用于在调用时实际上未与打开的文件关联的FILE
结构上(因为尝试关闭文件的错误将被忽略)。
该文件结构可能是以前打开的流,带有用户分配的缓冲存储器和缓冲策略。是freopen()
遵循这些设置,即重新将缓冲存储器/策略与“重新”打开的文件相关联,还是将结构重新初始化为默认值,假设用户free()
在[C0之后] d了缓冲存储器]之前是否已在文件中?
我接受。
[看第二季度,我没有看到标准库可靠地确定带有用户分配的缓冲存储器的当前未打开的fclose()
结构是否仍“拥有”该缓冲存储器,或者用户是否拥有该缓冲存储器的方法。已经回收了该内存。 (可以想象,该内存可能是本地的,即即使我愿意去那里也不是由FILE
/ malloc()
处理的内存列表的一部分,而且这是标准库函数所期望的非常不复杂的工作。)
缓冲策略的类似考虑。
因此,据我所知,唯一处理方式[free()
将“与指定流关联的任何文件”的关闭视为“真实” [C0 ],然后将缓冲存储器/策略重新设置为默认值。
整个freopen()
是(包括fclose()
):
对我来说,关键词是7.21.5.4 C11
freopen()
specification功能简介
[[1
freopen()
说明
[2 footnote 272函数打开名称为指向的字符串的文件
freopen
的值,并将stream指向的流与其关联。#include <stdio.h> FILE *freopen(const char * restrict filename, const char * restrict mode, FILE * restrict stream);
参数的用法与freopen
函数中的用法相同。272)3
如果filename
是空指针,则mode
函数将尝试执行以下操作:将流的模式更改为fopen
指定的模式,就像当前使用了与该流关联的文件的名称。由实现定义,允许哪些模式更改(如果任何),以及在什么情况下。[4
filename
函数首先尝试关闭任何与指定的流关联。无法关闭文件是忽略了。流的错误和文件结束指示符是已清除。返回
5如果打开操作,
freopen
函数将返回空指针失败。否则,mode
返回freopen
的值。272)
freopen
功能的主要用途是更改文件与标准文本流(freopen
,stream
或freopen
)相关联,例如这些标识符不必是该值可修改的左值可以分配stderr
功能返回的值。
将流指向的流与其关联。先前存在的[[stdin
指向的流]具有一个新文件关联-这就是所有。通过不对缓冲进行任何更改,在我看来这意味着保留了当前的缓冲状态,因为stdout
只是associating一个新的文件,并具有preexisting流模式。根据我的阅读,仅应对标准中明确指出的fopen
流进行更改。也请注意第4段:stream
函数首先尝试关闭与指定流关联的任何文件。
指定流。对我来说,结论似乎不可避免:freopen()
不会创建新的流。它只是将先前存在的流指向一个新文件-这就是全部。]此读数-当前流的缓冲区状态未修改-当前实现支持。它们不会修改现有流的缓冲状态。
FILE *
和freopen
(很可能是当前的Solaris实现)似乎都没有改变原始缓冲区的状态,除了在关闭文件之前刷新任何缓冲区之外。
freopen()
功能确实没有正确指定。 GLIBC freopen()
implementation:
应用用途
freopen()
函数通常用于将与the OpenSolaris/Illumos implementation,freopen()
和POSIX has this to say关联的预打开的流附加到其他文件。由于当freopen()
参数为stdin
时不需要实现支持任何流模式更改,因此可移植应用程序不能依赖于使用stdout
来更改流模式,因此不鼓励使用此功能。该功能最初是添加到ISO C标准中的,以便于将stderr
和pathname
更改为二进制模式。由于此模式下的NULL
字符对POSIX系统无效,因此在POSIX应用程序中不需要使用此功能。但是,即使忽略freopen()
,成功调用stdin
也会起作用。特别是对于常规文件,它会截断文件并将流的文件位置指示符设置为文件的开头。这些副作用可能是ISO / IEC 9899:1999标准中指定功能的方式的意外结果,但除非或直到ISO C标准被更改,否则成功调用stdout
的应用程序将在在诸如以下情况下符合系统要求的意外方式:
'b'
这将导致
file3仅包含第二次调用的输出。appl