2012-03-03 52 views
1

我只是想知道如何实现getchar()?它是否如下所示?以这种方式阅读单字节是非常低效的。它使用一些缓冲吗?如何实现getchar()?

Pseudo code: 

int getchar(){ 

char buf[1]; 
int n = read(0,buf,1); 
if(n < 1) 
    printf("Read failed"); 

return buf[0]; 
} 
+1

'ungetc()'的存在应该确认它需要使用* some *类型的缓冲。 – 2012-03-03 06:48:18

+0

有很多实现可供您查看,仅仅是谷歌搜索了。 – 2012-03-03 06:50:42

回答

2

考虑标准C库执行的数目,这是不可能提供一个明确的答案,但最常见的似乎遵循相同的一般准则。

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

我知道至少一个的情况下(glibc),其中文件可以任选地 - 经由一个额外的选项,以fopen() - 经由存储器映射被访问(即mmap())而非read()/write()。为了避免出现问题时通过调用更高级功能混合,如scanf()getchar()被迫使用相同的缓冲结构。

未经探查的信息,我更担心的是使用getchar()比由它的使用有关的任何性能问题的代码结构的复杂性。

+1

使用'mmap'来实现'FILE *'是不可能的。 glibc中的'mmap'支持只是在将非标准标志传递给'fopen'函数时使用的一个选项。这是因为在创建地图后文件截断将在您尝试访问不再存在的零件时产生'SIGBUS'。 – 2012-03-03 13:33:48

+0

@R ..:我编辑我的回答让这一点更加明确 - 已经撞到了'SIGBUS'问题我自己,我应该更加重视该部分... – thkala 2012-03-03 14:29:58

+1

注意,如果内核添加一个新的' mmap'标志代替SIGBUS'的'使用备用信号,并且如果该信号被反过来保留以供用户空间标准库实现,而不是应用程序(由并行线程所使用的内部信号很像)使用,这将是可能用'mmap'安全地实现stdio缓冲区。但是,我怀疑,相对于所有可能的努力而言,性能优势将会非常令人失望。 – 2012-03-03 21:29:13

0

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

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; 
}