【问题标题】:What does the size argument of setvbuf mean for an unbuffered stream?setvbuf 的 size 参数对于无缓冲流意味着什么?
【发布时间】:2018-03-24 10:48:01
【问题描述】:

函数setvbuf()可用于使流无缓冲:

#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
  • mode 作为_IONBF 传递时,size 参数的值是什么意思?

  • 会分配缓冲区吗?

  • 可以通过0吗?

【问题讨论】:

  • 您必须查看 CRT 的源代码。但是可以安全地假设 buffer 和 size 的值是不相关的,当您传递 buffer=NULL 并且永远不会使用非 NULL 缓冲区时不会发生分配。图书馆作者确实应用了最小意外原则。
  • 显然它应该在这种情况下被忽略,显然 0 是适当的传递值。 (也就是说,如果你传递了 0 以外的任何数字,它仍然会被忽略,并且不会分配任何内容,但是调用看起来会非常误导。)但是我刚刚看过的不同的两个手册页不会出来并明确地说出来。也许您可能想添加language-lawyer 标签?

标签: c file-io language-lawyer c-standard-library


【解决方案1】:

C 标准的当前版本 (C11) 说:

7.21.5.6 setvbuf 函数

概要

   #include <stdio.h>
   int setvbuf(FILE * restrict stream,
               char * restrict buf,
               int mode, size_t size);

说明

setvbuf 函数只能在stream 指向的流与打开的文件相关联之后并且在对流执行任何其他操作(对setvbuf 的不成功调用除外)之前使用。参数mode 确定如何缓冲流,如下所示:_IOFBF 导致输入/输出被完全缓冲; _IOLBF 导致输入/输出被行缓冲; _IONBF 导致输入/输出无缓冲。如果buf 不是空指针,则可以使用它指向的数组而不是setvbuf 函数分配的缓冲区273) 并且参数size 指定数组的大小;否则,size 可以确定由setvbuf 函数分配的缓冲区的大小。数组的内容在任何时候都是不确定的。

退货

setvbuf 函数在成功时返回零,如果为 mode 提供了无效值或如果请求无法得到满足,则返回非零。

条件时态的使用为库作者在如何实现setvbuf() 方面提供了很大的灵活性。

Steve Summit 是这样论证的:

如果mode 作为_IONBF 传递,显然size 应该被忽略,并且显然0 是传递的适当值。 (也就是说,如果您传递了 0 以外的任何数字,它仍然会被忽略,并且不会分配任何内容,但是该调用看起来会非常具有误导性。)但是我刚刚看过的两个不同的手册页没有出来并明确地说出来。

C 标准确实允许 size 在所有情况下都被忽略,并且对于无缓冲情况下忽略它是有道理的。

我找到了一个也有意义的替代方案:setvbuf() 仍然可以指定流输出函数要使用的缓冲区,静态的或分配的,只要流函数在返回时不保留任何未刷新的输出.例如,printf 可以使用此缓冲区来组合其输出并按块刷新它。 C 标准指定无缓冲流对写入输出流的系统句柄的每个字节使用系统调用。这些是超出标准范围的实施细节。

如果setvbuf() 确实尝试分配size 字节并失败,它可能会返回一个非零值并且不会使流无缓冲。仍然符合要求的意外行为。试试setvbuf(stdout, NULL, _IOFBF, SIZE_MAX);

【讨论】:

  • 这不是那么简单。即使您要求不缓冲,文本文件仍可能发生缓冲。诸如字符集翻译和处理行尾之类的东西可能需要一个(小)缓冲区。所有高度特定于操作系统。 CRT 通常会切换到一个小的内部缓冲区。看看吧。
猜你喜欢
  • 2020-10-12
  • 2017-08-20
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
相关资源
最近更新 更多