输入输出(后面简称 “IO”)是应用程序不可或缺的一种基本能力 。 为了保持设计上的精简 , C 语言并没有在核心语言层面提供对 IO 相关接口的支持 , 相反 , 采用了标准库的方式来实现 。 通过引用名为 stdio.h 的标准库头文件 , 我们便可以快捷地为 C 程序添加读取用户键盘输入、输出内容到控制台 , 乃至读写文件等一系列常规的 IO 功能 。
快速回顾 IO 接口的使用方法首先 , 让我们通过下面这段代码来快速回顾 , 应该如何在 C 语言中使用这些由标准库提供的 IO 接口 。
#include <stdio.h>
int main(void) {
printf(\"Enter some characters:\\");
FILE* fp = fopen(\"./temp.txt\" \"w+\");
if (fp) {
char ch;
while (scanf(\"%c\" &ch)) {
if (ch == 'z') break;
putc(ch fp);
else {
perror(\"File open failed.\");
fclose(fp);
return 0;
这里 , 在 main 函数内部 , 我们通过多种不同的方式 , 让程序与进程预设的 IO 流以及我们自行打开的 IO 流产生了交互 。
其中 , 代码第 3 行 , 通过 printf 函数 , 我们可以将指定的文本传送至标准输出流(stdout)中 。 紧接着 , 借助代码第 4 行的 fopen 函数 , 我们得以在当前目录下打开名为 “temp.txt” 的文件 , 并将其与一个特定的文件 IO 流相关联 。 而当文件打开失败时 , 通过代码第 12 行的 perror 函数 , 我们能够将特定的错误信息传送到标准错误流(stderr) 。 最后 , 在代码的第 7 行 , scanf 函数的调用可以让我们从标准输入(stdin)流中 , 读取从外部环境输入的信息 。
IO 接口的不同级别通常来说 , IO 接口可以被分为不同层次 。 其中 , C 语言提供的 IO 接口属于“标准 IO”的范畴 。 与其相对的 , 是名为“低级 IO”的另一套编程模型 。 顾名思义 , 低级 IO 会使用与具体操作系统相关的一系列底层接口来提供相应的 IO 能力 , 比如常用于 Unix 与类 Unix 操作系统上的 POSIX 接口标准 。 如果我们将上面的示例程序完全用该标准进行重写 , 将会得到如下所示的代码:
#include <unistd.h>
#include <fcntl.h>
int main(void) {
const char str[
= \"Enter some characters:\\";
write(STDOUT_FILENO str sizeof(str));
const int fd = open(\"./temp.txt\" O_RDWR | O_CREAT);
if (fd > 0) {
char ch;
while (read(STDIN_FILENO &ch 1)) {
if (ch == 'z') break;
【c语言|C语言标准IO的理解】write(fd &ch sizeof(ch));
else {
const char errMsg[
= \"File open failed.\";
write(STDERR_FILENO errMsg sizeof(errMsg));
close(fd);
return 0;
可以看到 , 在使用低级 IO 接口进行编程时 , 我们需要处理与所进行 IO 操作有关的更多细节 。 比如 , 在调用 write 接口时 , 你必须要指定不同的文件描述符(File Descriptor) , 才能够区分所要进行的操作是“向屏幕上输出字符” , 还是“向文件内写入数据” 。 相反 , 在高级 IO 的实现中 , 我们并不需要关注这些细节 , 接口的名称可以直接反映其具体用途 。
两者之所以会在接口使用粒度上存在差异 , 是由于“低级 IO 与操作系统实现紧密相关” 。 对于 POSIX 标准来说 , 其所在系统会将绝大多数的 IO 相关资源 , 比如文档、目录、键盘、网络套接字 , 以及标准输入输出等 , 以“文件”的形式进行抽象 , 并使用相对统一的数据结构来表示 。 而在实际编码过程中 , 每一个可用的 IO 资源都会对应于一个唯一的整型文件描述符值 。 该值将被作为“单一可信源(The Single Source of Truth)” , 供相关接口使用 。
而标准 IO 在接口设计与使用方式上 , 却不会与某类特定的操作系统进行“绑定” 。 相反 , 它会提供更加统一和通用的接口 , 来屏蔽底层不同系统的不同实现细节 , 做到“一次编写 , 到处编译” 。
除此之外 , 即使上述两段采用不同级别 IO 接口实现的 C 代码 , 在实际的可观测执行效果方面基本一致 , 但它们在程序运行时 , 资源的背后使用逻辑上却有着较大的差异 。
带缓冲的标准 IO 模型那么 , 这两种 IO 模型除了在接口使用方式上有不同外 , 还有哪些重要差异呢?简单来讲 , 与低级 IO 相比 , 标准 IO 会为我们提供带缓冲的输入与输出操作 。 事实上 , 标准 IO 接口在实现时 , 会直接使用所在平台提供的低级 IO 接口 。 而低级 IO 接口在每次调用时 , 都会通过系统调用来完成相应的 IO 操作 。
- 加州大学|马斯克脑机接口公司被指虐猴,参加实验的23只猴子死了15只
- 互联网|传统企业里,产品经理的价值衡量难题
- 企业|裁员,降薪,大牛出走:AI大退却的始末缘由
- 界面设计中的分割方式
- 权限|CRM 05:基于RBAC理论的权限设计
- 小米科技|家电升级计划:幸福感+N,盘点近期入手的家电好物
- 机箱|内外设置精致双屏幕,二手金立w900体验,国产翻盖手机中的贵族
- 算法|千人千面的算法,走到了十字路口
- 熟人|年轻人都在玩的“啫喱”,没撑过3天?
- 千人千面的算法,走到了十字路口