永发信息网

请问:关于C语言中getc(stdin) 读取键盘缓冲区中的输入的问题?

答案:1  悬赏:40  手机版
解决时间 2021-07-31 12:46
  • 提问者网友:贪了杯
  • 2021-07-30 18:18

C语言中:getc(stdin) 能取得键盘缓冲区中的一个字符:

如:

#include<stdio.h>

void main(void)
{
char a;
a=getc(stdin);
printf("%c",a);

}

以下是stdio.h 中的部分源码:

struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};


typedef struct _iobuf FILE;

_CRTIMP int __cdecl _filbuf(FILE *);

#define getc(_stream) (--(_stream)->_cnt >= 0? 0xff & *(_stream)->_ptr++ : _filbuf(_stream))

#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])

_CRTIMP int __cdecl getc(FILE *);

_CRTIMP extern FILE _iob[];

从上面我们知道,getc()的参数是 一个可以指向 FILE 类型的变量,同时也知道 getc()的实现

也知道 getc(stdin) 中的stdin 是(&_iob[0])。

所以我们知道 :

_stream=&_iob[0]; 从上面我们知道_iob[] 是一个FILE数组,

a=getc(stdin); 当程序执行到这里时,是怎么确定 _iob[0]._cnt的值的呢?

即:

问题1: --(_stream)->_cnt >= 0 中(_stream)->_cnt的值是那里来的?

问题2:0xff & *(_stream)->_ptr++,_ptr _ptr值是怎么来的?

问题3:_filbuf(_stream)) 是什么意思?

主要要问:

getc() 是怎么实现从 键盘缓冲区中取得一个字符的?

最佳答案
  • 五星知识达人网友:野慌
  • 2021-07-30 18:57

问题一:


首先得搞清楚stdin是什么:


#define stdin (&_iob[0])


然后再看_iob[0]:


#define _IOB_ENTRIES 20


typedef struct _iobuf FILE;


FILE _iob[_IOB_ENTRIES] = {



{ _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },



{ NULL, 0, NULL, _IOWRT, 1, 0, 0 },



{ NULL, 0, NULL, _IOWRT, 2, 0, 0 },


};


这是一个全局的FILE结构体数组。肯定在初始化的时候就已经成这样了。


所以第一个问题解决。


问题二也就解开了。


问题三:


_filbuf(_stream)) 中_filbuf是个函数,_stream是stdin也就是FILE _iob[0].


再看获取IO输入的调用流程:


getc的整个流程:
.exe!main()
.exe!_filbuf(_iobuf * str=0x0043d1c0) // #define getc( param ) _filbuf( param )
.exe!_read(int fh=0, void * buf=0x0043e800, unsigned int cnt=4096)
kernel32.dll!_ReadFile@20()
kernel32.dll!_ReadConsoleA@20()
kernel32.dll!_ReadConsoleInternal@32()
ntdll.dll!_CsrClientCallServer@16()
ntdll.dll!_ZwRequestWaitReplyPort@12()
ntdll.dll!_KiFastSystemCall@0()



_KiFastSystemCall@0()的反汇编代码是:
mov edx, esp
sysenter // 进驱动



因此 _filbuf就负责一直等待console的输入缓冲区里面有字符输入,然后填到FILE的buf里面,也就是(_stream)->_ptr所指向的这个缓冲区.

(_stream)->_cnt就是在filbuf里面设置的,读取了io,填到buff里面后,会修改这个cnt,表示buff里面有多少字符.


我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯