【问题标题】:Clarify the difference between input/output stream and input/output buffer明确输入/输出流和输入/输出缓冲区的区别
【发布时间】:2018-07-21 17:05:39
【问题描述】:

已编辑

输入流和输入缓冲区

据我了解,当在键盘上按下某个键时,字符会进入输入流 (stdin) 并存储在缓冲区中。然后scanf(在C的情况下)或cin(在C++的情况下)从缓冲区中提取字符并将其放入主内存中。

输出流和输出缓冲区

同样,在屏幕上显示字符之前,它们首先存储在缓冲区中。然后 printf(在 C 的情况下)或 cout(在 C++ 的情况下)从缓冲区中提取字符(当它已满时)并将其发送到输出(stdout)流。

我说的对吗?我已经坚持了很长一段时间了,我的逻辑可能有缺陷。

【问题讨论】:

  • 在抽象意义上,流是输入数据的任何连续源或输出数据的通道。流不一定是缓冲的(例如 GPIO 引脚上的模拟传感器),并且缓冲区只是可能与流没有任何关系的数据块(例如位图的光栅缓冲区)。 C++ 的 std 中的 Streams 类型也不一定是缓冲的。
  • C 和 C++ 标准库使用的流基本上是正确的。
  • @Dai 标准输入输出流被缓冲。
  • 我有点困惑。例如,人们建议在将字符串作为输入时使用 fgets() 函数而不是 gets() 函数,因为 gets() 可能会导致输入缓冲区溢出。在这种情况下缓冲区是什么意思?
  • 在此上下文中,它表示fgetsgets 读入的char 数组-fgets 提供了一种控制在数组中放置多少字符的方法,@987654325 @ 没有(并且是一个已弃用的函数)。

标签: c++ c


【解决方案1】:

旁注:scanf() 不是读取输入的函数,see more here


现在问你的问题:当询问 C(和 C++),例如语言时,你应该停留在语言提供的抽象概念中。所以,不要从键盘开始,这远远超出了你的程序。

从这里开始:操作系统想要向您提供一些输入。现在,您的 C 运行时为您的代码提供了一个 输入。 stream 是一个抽象的概念,它只是意味着你可以连续读取的东西。此流可以是缓冲或非缓冲的,如果它是缓冲的,则有不同的模式(完全缓冲或行缓冲)可用。您可以配置所有这些。

如果您的流没有缓冲,这意味着操作系统必须等到您的代码想要从输入流中读取数据。默认情况下,您的标准输入流是行缓冲,这意味着您的 C 运行时会立即接受输入并将其放入缓冲区中,直到出现换行符——您的代码调用输入函数将从那个缓冲区。

从概念上讲,输出也是如此,反之亦然。例如,如果您的输出流是行缓冲的,那么您的 C 运行时将填充一个缓冲区,直到出现换行符并将整行传递给操作系统进行输出。如果输出没有缓冲,则每个字符都会立即传递给操作系统。


免责声明:这仍然很简单,但应该足够开始了。


当您询问 cmets 中的术语“缓冲区溢出”时,提到 gets() - 这是关于您自己的代码中的缓冲区。对于读取多个值/字符的任何输入函数,您必须为其提供自己的缓冲区以将结果存储到其中。使用gets(),没有办法告诉函数这个缓冲区有多大,所以只要可用输入太大,它就会溢出它。这就是为什么 gets() 定义不明确并同时从 C 语言中删除的原因。它与可能用于 I/O 流实现的 C 运行时的缓冲区无关。

【讨论】:

  • 哇,这清除了我脑海中的很多混乱。因此,对于gets() 函数,术语“缓冲区溢出”适用于代码中的字符数组的大小?
  • 是的,这也是一个缓冲区,你自己定义。
猜你喜欢
  • 2014-09-14
  • 2015-01-09
  • 2017-12-10
  • 1970-01-01
  • 2021-12-19
  • 2014-04-27
  • 1970-01-01
  • 2019-08-02
  • 1970-01-01
相关资源
最近更新 更多