Search code examples
cprintfgetcharkernighan-and-ritchieputchar

getting a stream of -1 when I pass EOF in an infinite getchar printf loop (language: C)


i have just started K&R book. It introduces a getchar() putchar() loop program to copy characters from input to output until EOF is reached.

main()
{
    int c;

    while ((c = getchar()) != EOF)
        putchar(c);
}

I tried to change it to an infinite loop and see what happens when I try to print EOF instead. Here's the code:

#include <stdio.h>

int main() {
    int c;
    while(1) {
        c = getchar();
        if (c == EOF) {
            printf("%d", c);    // Since you cannot really use putchar() for EOF as it is -1
            // break;
        } else {
            putchar(c);
        }
    }
    putchar('\n');
    return 0;
}

Sample output:

./a.out 
a
a
-1
-1
df
df
-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1

I would have expected it to print -1 and then wait for the next input, but I have found is that it just keeps on printing -1.

If I add a line to break the loop after printing EOF once, it prints -1 once and then exits the program which is understandable.

But i don't understand why without the break statement it just keeps on looping and printing -1.

At first i thought it is somehow using the output -1 as the input for the next loop (next 2 loops actually since -1 is 2 separate characters '-' and '1'), but if that is the case why do I not see such infinite loop behavior when I put any other character like 'a', this should have printed 'a' continuously according to my previous logic.

Can someone help to explain what is going on?


Solution

  • According to §7.23.1 ¶6 of the ISO C23 standard, the function getchar is a "byte input function".

    §7.23.3 ¶11 states the following about the behavior of byte input functions:

    The byte input functions read characters from the stream as if by successive calls to the fgetc function.

    §7.23.7.1 ¶3 states the following about the function fgetc:

    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.

    This means that once the end-of-file indicator has been set, all further calls to byte input functions will always fail immediately, without making any attempt to read any more data. However, the end-of-file indicator can be cleared with the function clearerr. After doing that, depending on the platform, the next call to a byte input function may be successful.