According to the c++ draft 27.4.2:
The object cin controls input from a stream buffer associated with the object stdin, declared in <cstdio>.
Reading from std::cin
is the same as reading from stdin
. This means that after fclose(stdin)
using std::cin
is like calling scanf("%d", &a)
.
This is exactly what happens in the third case, where fclose(stdin)
is called before reading std::cin
. In contrast, cases 1-3 the code reads std::cin
before fclose(stdin)
.
Reading from a closed stdin
is possibly undefined. Here is what the c11 draft has to say about it:
7.21.7.1 The fgetc function
...
int fgetc(FILE *stream);
...
Returns:
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-
of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the
fgetc function returns the next character from the input stream pointed to by stream.
If a read error occurs, the error indicator for the stream is set and the fgetc function
returns EOF.
This text covers all cases of reading from an open stdin (successful, end-of-file, and a read error), but they don't refer to the case when the stream is closed due to fclose
. I could not find anything in the standard that covers this case, which means that the case is undefined.
Conclusion: reading from std::cin
after fclose(stdin)
, without any further freopen
is undefined behavior. Trying to read a closed C stream might refer to freed resources.