`getchar()` 返回错误的特殊情况是什么?

问题描述

所以我知道 getchar() 在输入结束或发生错误时返回 EOF。我也知道我可以检查 ferror(stdin)feof(stdin) 发生了哪些情况。 我想知道特别是什么情况下会发生错误

我检查了这两个函数的手册页,但那里没有任何相关内容

解决方法

所有的 stdio.h 都指向一个叫做 error indicator 的东西,它是一个内部变量,据说位于应用程序员无权访问的不透明 FILE 对象中(参见 C17 7.21 .1).

getchar 的文档可在 C17 7.21.7.6 中找到:

getchar 函数返回指向的输入流中的下一个字符 标准输入。如果流位于文件尾,则设置流的文件尾指示符,并且 getchar 返回 EOF。如果发生读取错误,则设置流的错误指示符并 getchar 返回 EOF。

所以我们不知道 getchar 返回 EOF 是因为它到达了流的末尾,还是因为出现了读取错误。为了知道,我们必须检查错误指示器。

这就是 ferror(stdin) 的用武之地。这是一个稍微有用的函数,因为它只执行此操作 (C17 7.21.10.3):

ferror 函数返回非零当且仅当错误指示符设置为 流。

这就是它的全部 - 这是一个标准化的、可移植的抽象层,我们无法真正知道幕后发生了什么。这很好,因为大多数时候我们根本不在乎。

在这些标准 C 函数下将有一个特定于操作系统的 API,在 POSIX 的情况下可能是 read(),在 Windows 的情况下可能是 ReadFile() 等。这些函数反过来可能会失败原因:不正确的文件句柄、文件被另一个进程占用、操作系统没有授予用户对文件的读取权限等。

理论上 getchar 也可以连接到嵌入式系统上的串行总线,在这种情况下,它失败的原因将与托管系统上的完全不同。现在我们突然在谈论错误的波特率、缓冲区溢出、帧错误或任何适用的问题。

,

getchar() 可以为多个系统特定的 I/O 错误返回 EOFgetchar() 被定义为等价于 getc(stdin),它本身等价于 fgetc(stdin),只是它可以作为一个宏来实现。以下是 linux man page 中 Linux 系统的可能原因列表:

返回值

成功完成后,fgetc() 将返回下一个字节 来自流指向的输入流。如果文件尾 流的指示符已设置,或者流是否在末尾 文件,应设置流的文件结束指示符,并且 fgetc() 应返回 EOF。如果发生读取错误,则错误 应设置流的指示符,fgetc() 应返回 EOF, 并应设置 errno 以指示错误。

错误

如果需要读取数据,fgetc() 函数将失败:

EAGAIN 为文件描述符设置了 O_NONBLOCK 标志 底层流和线程将在 fgetc() 操作。

EBADF 底层流的文件描述符不是有效文件 描述符打开以供阅读。

EINTR 由于收到一个 信号,没有数据传输。

EIO 发生物理 I/O 错误,或进程处于 后台进程组试图从其读取 控制终端,并且调用线程是 阻塞 SIGTTIN 或进程忽略 SIGTTIN 或 进程的进程组是孤立的。这个错误可能 也因实现定义的原因而生成。

EOVERFLOW 该文件是一个普通文件,并试图读取 等于或超过与相关的偏移最大值 对应的流。

如果出现以下情况,fgetc() 函数可能会失败:

ENOMEM 可用存储空间不足。

ENXIO 请求来自不存在的设备,或者请求 超出了设备的能力范围。