【问题标题】:How getchar() is implemented?getchar() 是如何实现的?
【发布时间】:2012-03-03 06:44:56
【问题描述】:

我只是想知道getchar() 是如何实现的?是不是像下面这样?以这种方式读取单字节的效率非常低。它是否使用一些缓冲?

伪代码:

int getchar() {

    char buf[1];
    int n = read(0, buf, 1);

    if(n < 1)
        printf("Read failed");

    return buf[0];
}

【问题讨论】:

  • ungetc() 的存在应该确认它需要使用 some 种类的缓冲。
  • 有很多实现供您查看,只需 google 搜索即可。

标签: c stdio


【解决方案1】:

这是一个非常简单的实现。

int mygetchar(void)
{
        static char buf[BUFSIZ];
        static char *bufp = buf;
        static int i = 0;

        if (i == 0)
        {
                i = read(0, buf, 1);
                bufp = buf;
        }
        if ( --i >= 0 )
        {
                return  *bufp++;
        }

        return EOF;
}

【讨论】:

    【解决方案2】:

    考虑到标准 C 库的实现数量,不可能提供明确的答案,但最常见的似乎遵循相同的一般准则。

    根据定义,getchar() 使用标准 C 库的流基础结构,即 FILE 及其友好函数。在大多数现代 C 库实现中,文件流在一定程度上被缓冲,缓冲区大小和行为通常可以通过 setvbuf() 进行调整。

    我知道至少有一种情况 (glibc),其中文件可以选择 - 通过fopen() 的额外选项 - 通过内存映射(即mmap())而不是read()/write() 访问.为避免与对更高级别函数(例如 scanf())的调用混合时出现问题,getchar()强制使用相同的缓冲结构。

    如果没有来自分析器的信息,我更担心使用 getchar() 的任何代码的结构复杂性,而不是使用它引起的任何性能问题。

    【讨论】:

    • 不可能用mmap实现FILE *。 glibc 中的mmap 支持仅在您将非标准标志传递给fopen 函数时使用。这是因为在创建映射后文件截断会导致当您尝试访问不再存在的部分时SIGBUS
    • @R..:我编辑了我的答案以更清楚地说明这一点 - 我自己遇到了SIGBUS 问题,我应该更加关注那部分......
    • 请注意,如果内核添加了一个新的mmap 标志以使用替代信号代替SIGBUS,并且如果该信号又被保留供用户空间标准库实现使用而不是应用程序(很像 pthreads 使用的内部信号),可以使用mmap 安全地实现 stdio 缓冲区。但是,我怀疑相对于为实现这一目标所付出的所有努力,性能优势会非常令人失望。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 2011-04-26
    • 2015-05-22
    • 2015-04-22
    • 2020-07-31
    相关资源
    最近更新 更多