为什么 read() 在 scanf() 之后不起作用?

why doesn't read() work after scanf()?

好的,这是一个愚蠢的问题,我确定我 "should" 知道这个,但不知何故我不知道...

FILE 结构包装文件描述符,所以如果我 fscanf 那应该推进文件描述符。

但是这个程序编译为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

似乎文件描述符没有前进,因为第一个 read 读取 b。更令人惊讶的是,第二个也读作 b(尽管,如果我省略 scanf,那么第一个 read 读作 b,第二个读作 c).

我相信这是显而易见的,我真的不好意思问为什么。我之前从来没有关注过 scanfread

我知道 scanf 总的来说是个坏主意,但在我的情况下还可以,因为我控制着管道的另一端,而且这样做对我来说很方便。

stdin 流本身将执行 read 来填充整个缓冲区,这可能有数千个字符宽。这对您的 read 系统调用没有任何影响。 scanf 只是从缓冲区中提取字符。

您随后的 read 系统调用实际上是 returning 0(由于文件末尾没有读取字节)并且没有将任何数据放入 c,因此保留其值'b'。您的程序没有注意到这种情况,因为它没有检查 return 值。