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
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.