一段时间以来,我一直试图了解 K&R 的 putc 版本,但我没有资源(谷歌、堆栈溢出、clcwiki 没有我要找的东西,而且我没有 friend 或同事可以求助)至)。我会先解释上下文,然后再要求澄清。

本章介绍了一个描述文件的数据结构的例子。该结构包括一个字符缓冲区,用于一次读取和写入大块。然后他们要求读者编写标准库 putc 的一个版本。

作为给读者的线索,K&R 编写了一个支持缓冲和非缓冲读取的 getc 版本。他们还编写了 putc 宏的框架,让用户自己编写函数 _flushbuf()。 putc 宏看起来像这样(p 是指向文件结构的指针):

int _flushbuf(int, FILE *);
#define putc(x,p)        (--(p)->cnt >= 0 \
                       ? *(p)->ptr++ = (x) : _flushbuf((x),p)
typedef struct {
        int   cnt;  /*characters left*/
        char *ptr;  /*next character position*/
        char *base; /*location of buffer*/
        int   flag; /*mode of file access*/
        int   fd;   /*file descriptor*/
} FILE;

令人困惑的是,宏中的条件实际上是在测试结构的缓冲区是否已满(这在文本中进行了说明)- 作为旁注,getc 中的条件完全相同,但意味着缓冲区为空。奇怪的?

这是我需要澄清的地方:我认为 putc 中的缓冲写入存在很大问题;由于写入 p 仅在 _flushbuf() 中执行,而 _flushbuf() 仅在文件结构的缓冲区已满时才调用,因此只有在缓冲区完全填满时才会进行写入。缓冲读取的大小始终是系统的 BUFSIZ。不会写除 'BUFSIZ' 字符以外的任何字符,因为 _flushbuf() 永远不会在 putc 中被调用。

putc 适用于无缓冲写入。但是宏的设计使得缓冲写入几乎完全没有意义。这是正确的,还是我在这里遗漏了什么?为什么会这样?我真的很感激这里的任何帮助。

最佳答案

如果你写得足够多,缓冲区最终会变满。如果不这样做,您最终将关闭文件(或者运行时会在 main() 返回时为您关闭)并且 fclose() 调用 _flushbuf() 或其等效项。或者您将手动 fflush() 流,这也相当于 _flushbuf()

如果您要写几个字符然后调用 sleep(1000) ,您会发现很长一段时间都没有打印任何内容。这确实是它的工作方式。

getc 和 putc 中的测试是相同的,因为在一种情况下,计数器记录有多少字符可用,而在另一种情况下,它记录有多少可用空间。

关于c - 了解 K&R 的 putc 宏 : K&R Chapter 8 (The Unix System Interface) Exercise 2,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51486052/

10-14 10:58