Huh!!How shall I put the whole thing in a clear question!!Let me try:
I know that the files opened using fopen()
are buffered into memory.We use a buffer fo
A good mental model of the put back character is simply that it's some extra little property which hangs off the FILE *
object. Imagine you have:
typedef struct {
/* ... */
int putback_char;
/* ... */
} FILE;
Imagine putback_char
is initialized to the value EOF
which indicates "there is no putback char", and ungetc
simply stores the character to this member.
Imagine that every read operation goes through getc
, and that getc
does something like this:
int getc(FILE *stream)
{
int ret = stream->putback_char;
if (ret != EOF) {
stream->putback_char = EOF;
if (__is_binary(stream))
stream->current_position--;
return ret;
}
return __internal_getc(stream); /* __internal_getc doesn't know about putback_char */
}
The functions which clear the pushback simply assign EOF
to putback_char
.
In other words, the put back character (and only one needs to be supported) can actually be a miniature buffer which is separate from the regular buffering. (Consider that even an unbuffered stream supports ungetc
: such a stream has to put the byte or character somewhere.)
Regarding the position indicator, the C99 standard says this:
For a text stream, the value of its file position indicator after a successful call to the
ungetc
function is unspecified until all pushed-back characters are read or discarded. For a binary stream, its file position indicator is decremented by each successful call to theungetc
function; if its value was zero before a call, it is indeterminate after the call. [7.19.7.11 Theungetc
function]
So, the www.cplusplus.com reference you're using is incorrect; the behavior of ftell
is not undefined when there are pending characters pushed back with ungetc
.
For text streams, the value is unspecified. Accessing an unspecified value isn't undefined behavior, because an unspecified value cannot be a trap representation.
The undefined behavior exists for binary streams if a push back occurs at position zero, because the position then becomes indeterminate. Indeterminate means that it's an unspecified value which could be a trap representation. Accessing it could halt the program with an error message, or trigger other behaviors.
It's better to get programming language and library specifications from the horse's mouth, rather than from random websites.