Each stream has \"an error indicator that records whether a read/write error has occurred\".
It is set, usually rarely, by various functions: fgetc(
Here is a very crude, very minimal program to explore the behaviour of GNU C library with respect to fgetc()
, ferror()
, and feof()
, as requested by OP in a comment:
#define _POSIX_C_SOURCE 200809L
#include
#include
#include
#include
#include
#include
static volatile sig_atomic_t interrupted = 0;
static void interrupt_handler(int signum)
{
interrupted = 1;
}
static int install_interrupt(const int signum)
{
struct sigaction act;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = interrupt_handler;
act.sa_flags = 0;
if (sigaction(signum, &act, NULL) == -1)
return -1;
return 0;
}
int main(void)
{
int n, c;
if (install_interrupt(SIGALRM)) {
fprintf(stderr, "Cannot install SIGALRM handler: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
if (ferror(stdin)) {
fprintf(stderr, "Standard input is already in error state.\n");
return EXIT_FAILURE;
}
if (feof(stdin)) {
fprintf(stderr, "Standard input is already in end-of-input state.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Testing stream error state. Please wait.\n");
alarm(1);
c = fgetc(stdin);
if (c != EOF) {
fprintf(stderr, "Stream error state test failed.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "fgetc(stdin) returned EOF.\n");
fprintf(stderr, "ferror(stdin) returns %d.\n", ferror(stdin));
fprintf(stderr, "feof(stdin) returns %d.\n", feof(stdin));
fprintf(stderr, "\n");
fprintf(stderr, "Testing stream end-of-input state. Please press Ctrl+D.\n");
c = fgetc(stdin);
if (c != EOF) {
fprintf(stderr, "fgetc() returned %d; EOF was expected.\n", c);
return EXIT_FAILURE;
}
fprintf(stderr, "fgetc(stdin) returned EOF.\n");
fprintf(stderr, "ferror(stdin) returns %d.\n", ferror(stdin));
fprintf(stderr, "feof(stdin) returns %d.\n", feof(stdin));
if (!ferror(stdin) || !feof(stdin)) {
fprintf(stderr, "Expected error and end-of-file states; aborting.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "\n");
fprintf(stderr, "Testing fgetc() when stream in error and end-of-file state.\n");
fprintf(stderr, "Please type something, then press Enter.\n");
n = 0;
c = fgetc(stdin);
while (c != EOF && c != '\n') {
n++;
c = fgetc(stdin);
}
if (c == EOF) {
fprintf(stderr, "Further input is not possible.\n");
return EXIT_FAILURE;
} else
fprintf(stderr, "Further input is possible: %d characters (including Enter) read.\n", n + 1);
return EXIT_SUCCESS;
}
When I compile and run the above on Linux, the program will output
Testing stream error state. Please wait.
fgetc(stdin) returned EOF.
ferror(stdin) returns 1.
feof(stdin) returns 0.
The error state was caused by having signal delivery interrupt an fgetc(stdin)
call. As you can see, it does cause ferror(stdin)
to return nonzero. Note that feof(stdin)
returns 0, though.
The output continues:
Testing stream end-of-input state. Please press Ctrl+D.
Pressing Ctrl+C yields output
fgetc(stdin) returned EOF.
ferror(stdin) returns 1.
feof(stdin) returns 1.
At this point, the standard input is in both error and end-of-file states. The output continues:
Testing fgetc() when stream in error and end-of-file state.
Please type something, then press Enter.
If we now type say O K Enter, we get
Further input is possible: 3 characters (including Enter) read.
This proves that at least the GNU C library implementation does not check the stream error or end-of-file status at all. It will simply try to read more data (using the underlying read()
operation in POSIXy systems).