3

The C reference states that a FILE* opened in update mode ('+') needs to take the following two precautions:

  • Output cannot be followed by input without a call to one of fflush, fseek, fsetpos, or rewind.
  • Input cannot be followed by output wihout a call to one of fseek, fsetpos, or rewind.

I've learned that fflush suffices to allow input after output, because a FILE* opened in + mode often uses the same buffer for read and write operations. As a result, not using fflush before input might cause data to be mistakenly read from the buffer (which might not have been flushed, and thus contains data that still needs to be outputted).

However, in order for fseek, fsetpos, and rewind to achieve the same effect, this implies they must internally flush the buffer of the stream passed to them.

Does the C standard require that fseek, fsetpos, and rewind flush the buffer of their streams? If not, why not?

Telescope
  • 2,068
  • 1
  • 5
  • 22

2 Answers2

0

For reference only

When a file is opened with update mode (’+’ as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations.
C23dr § 7.23.5.3 7

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Grepping for "flush" in the C17 standard, the only actions that are guaranteed to flush the buffer are fclose(), fflush(), exit(), and returning from main. Additionally, it is implementation-defined whether abort() or _Exit() perform a flush. There is no indication that fseek() and friends would be guaranteed to do so.

The requirement to call fseek etc is to allow for primitive stdio implementations that don't keep track of whether the last operation was a read or write, nor of whether or how much of the buffer is dirty. But a smarter implementation might very well keep track. In that case there would be no need for fseek to perform a flush, as the flush would be done as needed by subsequent read/write operations. There is no good reason for the standard to defeat such optimizations by requiring a flush where it isn't needed.

If the programmer specifically wants the buffer to get flushed, they should just call fflush() rather than relying on the seek to do it for them. Even if it happens to be redundant on a particular implementation, the extra cost should be negligible, as flushing a buffer that is already empty should just do nothing.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82