C标准并没有规定缓冲区状态以任何方式被修改。
整个C11 freopen()
规范(包括脚注 272)如下:
7.21.5.4 The freopen
function
Synopsis
1
#include <stdio.h>
FILE *freopen(const char * restrict filename,
const char * restrict mode,
FILE * restrict stream);
Description
2 The freopen
function opens the file whose name is the string pointed
to by filename
and associates the stream pointed to by stream with it.
The mode
argument is used just as in the fopen
function.272)
3 If filename
is a null pointer, the freopen
function attempts to
change the mode of the stream to that specified by mode
, as if the
name of the file currently associated with the stream had been used.
It is implementation-defined which changes of mode are permitted (if
any), and under what circumstances.
4 The freopen
function first attempts to close any file that is
associated with the specified stream. Failure to close the file is
ignored. The error and end-of-file indicators for the stream are
cleared.
Returns
5 The freopen
function returns a null pointer if the open operation
fails. Otherwise, freopen
returns the value of stream
.
272) The primary use of the freopen
function is to change the file
associated with a standard text stream (stderr
, stdin
, or stdout
), as
those identifiers need not be modifiable lvalues to which the value
returned by the fopen
function may be assigned.
对我来说,关键短语是“将指向流的流与它相关联”。原先由
stream
指向的流与一个新文件相关联,就这样。由于未指定对缓冲区的任何更改,这意味着当前缓冲区状态被保留,因为
freopen()
只是将一个新文件和模式与
预先存在的 流相关联。根据我的理解,只应执行标准中明确记录的对
FILE *
流的更改。
另请注意第4段:
freopen
函数首先尝试关闭与指定流相关联的任何文件。再次,标准涉及到
指定流。
对我而言,结论似乎不可避免:
freopen()
不会创建新流。它只是将预先存在的流指向一个新文件,仅此而已。
这种阅读方式——即当前流的缓冲状态不会被修改——得到了当前实现的支持。它们不会修改预先存在的流的缓冲状态。
无论是
GLIBC freopen()
实现 还是
OpenSolaris/Illumos 实现(很可能是当前 Solaris 实现)似乎都不会修改原始缓冲状态,除了在关闭文件之前刷新任何缓冲区。
freopen()
函数似乎规范不佳。
POSIX 这样说:
APPLICATION USAGE
The freopen()
function is typically used to attach the pre-opened streams associated with stdin
, stdout
, and stderr
to other files.
Since implementations are not required to support any stream mode changes when the pathname
argument is NULL
, portable applications cannot rely on the use of freopen()
to change the stream mode, and use of this feature is discouraged. The feature was originally added to the ISO C standard in order to facilitate changing stdin
and stdout
to binary mode. Since a 'b'
character in the mode has no effect on POSIX systems, this use of the feature is unnecessary in POSIX applications. However, even though the 'b'
is ignored, a successful call to freopen (NULL, "wb", stdout)
does have an effect. In particular, for regular files it truncates the file and sets the file-position indicator for the stream to the start of the file. It is possible that these side-effects are an unintended consequence of the way the feature is specified in the ISO/IEC 9899:1999 standard, but unless or until the ISO C standard is changed, applications which successfully call freopen (NULL, "wb", stdout)
will behave in unexpected ways on conforming systems in situations such as:
{ appl file1; appl file2; } > file3
which will result in file3 containing only the output from the second invocation of appl.
FILE *
为NULL
,否则返回与传递给函数的相同的FILE *
(“...流的值”)。所以很遗憾,情况并不是那么明确。 - DevSolarFILE
结构中添加一个filename
插槽来实现freopen(NULL, mode, stream)
的可疑规范:我怀疑这不是必要的也不足够,并且您在实现中有一个愚蠢的错误:stream->filename = (char *)malloc( strlen( filename ) )
。一定要使用strdup()
,它最终将进入下一个C标准。 - chqrlie