GetChar caching mechanism in depth analysis

  • 2020-04-02 01:29:35
  • OfStack

Associated with buffer zone is the most common operation characters of the input and output operations getchar, getc, getch, getche, gets series function.

The first example (related to getchar) :


#include<stdio.h>  
int main()  
{  
    int ch;  
    ch=getchar();  
    ch=getchar();  
    printf("%dn",ch);  
    return 0;  
}  

Enter a character code as above, when press enter after the program did not wait for you the second input is over, and no matter what input operation result are 10, isn't it strange, anyway, feeling is very strange when I first met), what is more strange when you one-time input more characters such as abcd results correct print 98, why? That's the reason for the buffer.

Getchar is defined in the stdio.h file, and we can find its related definition in stdio.h:


#define getchar()         getc(stdin)//Getchar is the same thing as calling getc(stdin)

We find the definition of getc again

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

Expand it to:

if(--(stdin)->_cnt>=0)  
      return 0xff&*(stdin)->ptr++;  


else  
        return filbuf(stdin);  

Stdin is the standard input stream. If you look at MSDN and stdio.h, you can see the following definition:

Stdio.h:


#define stdin  (&_iob[0])  

Follow up:

_CRTIMP extern FILE _iob[];  

From the above code, it can be seen that _iob is of the type of FILE structure. If you look at stdio.h, you can see that the FILE structure is defined as follows:

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

From the FILE structure we can get the _cnt and _ptr members used in the above getc macro definition, but these are secondary, we should not be difficult to find such a few members _bufsize,_base corresponding to the buffer size, the buffer base address, from here we can get an obvious conclusion that getchar function USES the buffer mechanism. (_cnt corresponds to the number of bytes input to the buffer, _ptr to the position of the read pointer)

Getc macro definition details


--(stdin)->_cnt>=0  

This sentence determines whether there is data in the buffer. If there is, subtract one (to indicate that another has been read) and read the data return 0xff&*(stdin)- > P TRS ++, after reading, move the read pointer forward one position [important]

All right, so that's the setup, but let's get back to where we are :)

Appear afore-mentioned results trace knot bottom or because the getchar function using the buffer (see above, I think you also know, really use the buffer), press enter when enter a character after the program did not wait for you the second input is over, and no matter what the input operation result are 10, this is because when the user to enter a character, and press enter, the characters will be deposited in the user input in the buffer and linefeed ASCII (10 -) 【 omit enter ASCII 13, possibly to cross-platform, under Linux, is after the newline 10, Under Windows enter is to return back to the first line first, then a newline, namely 13 10 】 (executed first getchar is actually getc else statements, after filling buffer _cnt = 2, _prt pointed to zero position, after the execution _cnt = 1, _prt points to 1 location), the second, when performing a getchar call getc won't execute the else statement, execution is the if statement, so the second no longer wait for user input, direct execution, execution after the CNT = 0, PRT to position 2, and returns the result of PTR point in position 1, That is, 10. Since 10 is a newline key, when execution encounters this point, the cache will be cleared after execution, PTR points to the position 0 again, and CNT =0.

The analysis is the same when typing ABC, except that after sweeping the second getchar, CNT =2, PTR points to position 2.


Related articles: