How a stream error indicator affects following input code?

Assuming no UB, are 5 of the 8 possible and not the 3 unexpected ones?
especially is valid input possible with error indicator set?

Speaking specifically to the provisions of the standard, I’m inclined to agree with your analysis:

  • Few functions are specified to clear the error indicator of a stream, and fgetc() is not one of them. More generally, none of them are data-transfer functions. Therefore, if the error indicator is set for a stream before that stream is presented to fgetc() for reading, then it should still be set when that function returns, all other considerations notwithstanding. That covers these cases:*

    1  0   0   Unexpected
    1  1   0   Unexpected
    1  1   1   Input error or end-of-file
    

    It also covers this case with respect to the expected value of the error indicator, though it does not speak to whether it can actually happen:

    1  0   1   Normal reading of valid data with error indicator set!
    
  • fgetc() is specified to return EOF in every situation in which it is specified to set the end-of-file indicator on a stream. Therefore, if fgetc() returns anything other than EOF then it will not, on that call, have set the stream’s error (or end-of-file) indicator. That covers these cases:

    0  0   0   Normal reading of valid data    
    0  0   1   Unexpected
    

    On the other hand, if fgetc() does return EOF then either the stream’s end-of-file indicator or its error indicator should afterward be found set. But the standard distinguishes between these cases, and specifies that the user can distinguish them via the feof() and ferror() functions. That covers these cases:*

    0  1   0   End-of-file
    0  1   1   Input error
    
  • Finally, I concur that none of the behavior of fgetc() is conditioned on the initial state of the stream’s error indicator. Provided only that the stream is not initially positioned at its end, and its end-of-file indicator is not initially set, “the fgetc function returns the next character from the input stream pointed to by stream.” That establishes that this, the case of most interest, is in fact allowed:

    1  0   1   Normal reading of valid data with error indicator set!
    

    However, that the case is allowed in the abstract does not imply that it can be observed in practice. The details seem unspecified, and I would expect them to depend on the implementation of the driver serving the stream in question. It is entirely possible that having once encountered an error, the driver will continue to report an error on subsequent reads until reset appropriately, and perhaps longer. From the C perspective, that would be interpreted as an (additional) error occurring on each subsequent read, and nothing in the language specifications prevents that. Not even use of one of the functions that clear a stream’s error indicator.

If codes does not clear the error indicator before hand and wants to
detect if a line of input had a rare input error, it seems to make
sense to test !feof() and not ferror() to detect.

Is checking ferror() potentially misleading? or have I missed something about the error indicator?

I agree that if a stream’s error indicator is initially set, its end-of-file indicator is not, and reading it with fgetc() returns EOF, then ferror() does not usefully distinguish between the end-of-file and error cases whereas feof() should.

On the other hand, whether one can usefully continue to read a given stream after an error has been encountered on it depends on implementation and possibly on specific circumstances. That applies even if the error indicator is cleared via a clearerr() call, not to mention if the error indicator is not cleared.


* Although I agree that there is an ambiguity with respect to EOF in the event that UCHAR_MAX > INT_MAX, I assert that that is just one of several reasons why such an implementation would be problematic. As a practical matter, therefore, I disregard such implementations as entirely hypothetical.

Leave a Comment