OK this is a stupid question, I am sure I "should" know this but somehow I don't...
FILE
structure wraps file descriptor, so if I fscanf
that should advance the file descriptor.
But for this program compiled to foobar
:
#include <stdio.h>
#include <unistd.h>
int main() {
char c;
scanf("%c", &c);
printf("scanned %c\n", c);
read(STDIN_FILENO, &c, 1);
printf("read %c\n", c);
read(STDIN_FILENO, &c, 1);
printf("read %c\n", c);
}
>echo bcd | ./foobar
scanned b
read b
read b
appears the file descriptor did not advance, because the first read
reads b
. What is even more surprising, the second one also reads b
(even though, if I omit the scanf
, then first read
reads b
and the second one, c
).
I am sure this is obvious and I am really embarrased to ask why. I just never followed scanf
with read
before.
I know scanf
is a bad idea overall, but in my case it is OK because I control the other end of the pipe, and it is convenient for me to do this sequence.
The stdin
stream will itself perform a read
to fill an entire buffer, which is likely thousands of characters wide. This leaves nothing for your read
system calls. scanf
just pulls characters from that buffer.
Your subsequent read
system calls are actually returning 0 (no bytes read due to end of file) and not putting any data in c
, which therefore retains its value 'b'
. Your program is oblivious to the situation because it isn't checking the return value.