You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言fgetc()与read()函数输入处理差异及缓冲机制疑问

问题解答:fgetc()与read()输入剩余字符的差异原因

确实和输入缓冲机制直接相关,核心在于两个函数分属不同层级的IO接口,缓冲逻辑完全不同:

1. fgetc()的行为(标准C库IO)

fgetc()是标准C库提供的高层IO函数,默认情况下,当stdin关联终端设备时,标准库会启用行缓冲:

  • 输入的字符会先暂存在终端的行缓冲区,直到按下回车,整行数据才会被送入标准库的缓冲区。
  • fgetc()从标准库缓冲区读取1个字符('h')后,剩余的"ello\n"仍留在标准库缓冲区中。
  • 程序终止时,C标准库会自动清理所有标准IO流的缓冲区,剩余字符不会被终端的shell读取,因此看起来"直接消失"。

对应代码示例:

//code1.c
#include <stdio.h>

int main(void)
{
  char ch;
  
  ch = fgetc(stdin);

  return 0;
}

2. read()的行为(系统调用IO)

read()是操作系统提供的底层系统调用,直接与内核的文件描述符交互,完全绕过了C标准库的缓冲机制:

  • 输入"hello\n"后,终端的行缓冲会把整行数据送入内核的输入缓冲区。
  • read()仅从内核缓冲区读取1个字节('h'),剩余的"ello\n"仍留在内核缓冲区中。
  • 程序终止后,终端的shell会继续从内核输入缓冲区读取数据,把剩下的"ello"当作命令执行,这就是你看到的现象。

对应代码示例:

//code2.c
#include <unistd.h>

int main(void)
{
  char ch;

  read(STDIN_FILENO, &ch, 1);

  return 0;
}

补充验证

如果想让第二个程序避免剩余字符被shell执行,可以在read()后手动读取并丢弃内核缓冲区中剩余的所有字符,比如:

#include <unistd.h>

int main(void)
{
  char ch;
  char buf[1024];
  
  read(STDIN_FILENO, &ch, 1);
  // 读取剩余缓冲直到遇到换行或EOF
  while (read(STDIN_FILENO, buf, sizeof(buf)) > 0);

  return 0;
}

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 10:32:40