Search code examples
c

Read is blocked by getc


For the following code:

#include <unistd.h>
#include <stdio.h>

int main()
{
    char buf[6];

    printf("%c\n", (char)getc(stdin));
    int ret = read(STDIN_FILENO, buf, 5);
    printf("%d\n", ret);
    printf("%c\n", (char)getc(stdin));
}

When using "abcdef" as the input, the system outputs

a
0
b

I think this means that read cannot get anything in this case. However, when comment out the first getc call, the system outputs

5
f

I think this means that read can get something.

My question is: how to avoid the block of read from getc? BTW: you can re-pro the behavior from https://godbolt.org/z/EaPTMWPz9


Solution

  • This is just a question about buffering. The first getc reads a lot more than one byte from the file. Note, "file" here is ambiguous, as there are several layers of abstraction, but I don't want to worry about the details.

    Basically, reading from a file is slow, and the system makes things faster by doing slow things as rarely as possible. When you call getc the first time, the system reads a bunch of data from the underlying stream, something like 4096 or 8192 bytes, or some reasonable size for the platform. Calling read after getc returns 0, because the system already read all of the data. The next getc returns data from the buffer that was written by the first getc.

    If you call read before you call getc, then no data has been buffered and is still available to be read.

    Basically, calling read attempts to bypass the buffering that getc is doing.