Take you to understand the input and output buffer area (super detailed explanation)

Take you to understand the input and output buffer area (super detailed explanation)

1.The meaning of cache area

Buffer , also called cache , is a part of memory space. In other words, a certain amount of storage space is reserved in the memory to temporarily store input or output data. This reserved space is called a buffer. Buffers are divided into input buffers and output buffers according to whether they correspond to input devices or output devices .

For example, I believe that when washing clothes, people tend not to take an old piece of clothing to the washing machine and wash it immediately, but wait for a few more items to be washed together. This can also avoid the waste of water and electricity resources. In the same way, the computer's cache area also uses the same idea.
In short, the cache area is a piece of memory, used as a temporary storage point for data, and plays a vital role in input and output operators.

2. Classification of cache

1. Full caching

It will wait until the entire cache area is filled before the cache will be refreshed. The most typical example is disk files. Files are opened using standard IO and are fully cached by default. Disk operations are performed only when the cache area is full or a flush operation is performed.

For example, there is a storage area in the memory, such as 64 bytes in size, and a program will read data from this storage area. The system puts the contents of a file into this area. As long as 64 bytes are filled, the program will immediately read the 64 bytes of data. As long as the 64 bytes are not full, even if only 63 bytes are placed, the program will not read it. This is what complete buffering means.

2. No buffering

Input and output operations are not cached, and reads and writes to the stream can operate on the actual file immediately. The standard error condition stderr is a typical example, which allows the error message to be displayed directly as quickly as possible.

3. Row caching

That is, when a line ends, the cache will start to be refreshed. If you want to refresh the line cache, just use the newline character ' \n ' and it will succeed, that is, the enter key (enter) . Among them, the most common one is the input and output cache (printf, scanf ) is the row cache. (This is also our focus today!!!)

Supplement : If we do not set the buffer ourselves, the system will set a buffer for standard input and output by default. The size of this buffer is usually 512 bytes. The buffer size is defined by the macro BUFSIZ in the stdio.h header file
Insert image description here

Next, we will focus on the input and output cache (line cache) that we are most exposed to.

3.1 Output buffer area

In the C language, many output functions (such as printf, putchar) have output caches. Under the window system, after using the printf() function, the data is written to the output buffer area , and then the buffer area is refreshed immediately , so when we use printf () function is often printed out on the console quickly (the Linux operating system is slightly different, so we will not demonstrate it here)

3.2 Input buffer area

Similar to the output function, the input function (scanf, getchar) also has an input cache, and these input functions are blocking functions . When there is no content in the buffer area , the program will block in the input function , waiting for the user to input content from the keyboard and press Press the Enter key (i.e. line feed '\n') to confirm. After that, the entered characters will enter the input buffer area. The input function will obtain the characters from the buffer area, delete the characters already obtained in the buffer area, and unblock the state to continue executing the code .

The following is an example of a very classic C language code to demonstrate the existence of input cache.

#include<stdio.h>
int main()
{
    
    
	char str[10];
	int i;
	for(i=0;i<10;i++)
		scanf("%c",&str[i]);        
	for(i=0;i<10;i++)
		printf("%c",str[i]);
	return 0;
}

The above program gets 10 characters and then prints them out. If we input 10 characters normally, the printing will be normal.
Insert image description here
However, in the following program, if we enter a, then enter, then b, then enter... the result is that we can only enter 5. The program ends after printing characters. This is actually the so-called scanf().
Insert image description here
Analysis of carriage return : First, when the program runs to the scanf of the first cycle, the buffer is empty at this time , that is, blocking occurs . We Enter a, and then press Enter. At this time, the buffer area actually contains two characters , 'a' and '\n'. Then the scanf at this time gets the character a, and the first loop ends (note that there are still two characters left in the buffer area at this time) A '\n'). Start the second cycle. However, scanf finds that there is a '\n' in the cache , so it will not block . At this time , scanf reads this '\n' . Then it starts the third cycle, and this When the buffer area is empty , blocking occurs again , so we wait for keyboard input again. We enter b and press Enter again. At this time, the buffer area contains two characters again , 'b' and '\n', and then repeat The above process. To sum up, the for loop equivalent to ten times of this loop will get '\n' at the even numbered times . This is why the abcde is printed vertically when printed later.

3. Input function without caching

The input function with cache was introduced earlier. Only when the Enter key is pressed, the input string can enter the cache area and wait for the program to read. Next, we introduce an input function without caching (_getch). As long as the keyboard is pressed, the program immediately obtains the input string. _getch obtains key values ​​directly from the keyboard without waiting for the user to press Enter. As long as the user presses a key, _getch will immediately end the input. In other words, there is no need to save the entered characters in the buffer area. In other words, if you enter a character, it will Read now

#include<stdio.h>
#include<conio.h>
int main()
{
    
    
	while (1)
	{
    
    
		char c;
		c = _getch();   //输入后用putchar打印
		putchar(c);
		if ('q' == c)
			break;
	}
	return 0;
}

Enter "abcq", the program immediately displays 'abcq' and exits, as shown below.
Insert image description here
This is because _getch is equivalent to uncached getchar (or a single read sancf function). When the program runs to the _getch function, it will enter the blocking state and wait for the keyboard. Directly input a character and press a key (no need to press Enter to enter the input buffer), the getch function will immediately receive the corresponding character (but will not be displayed on the console), and then print it on the console through putchar . In short, this is a function without display, that is, the console abcq is completely the function of putchar, and _getchar will not display the content (without display), so this function can be used in passwords

Next, compare the results if you switch to the scanf console.

#include<stdio.h>
#include<conio.h>
int main()
{
    
    
	while (1)
	{
    
    
		char c;
		scanf("%c",&c);   //输入后用putchar打印
		putchar(c);
		if ('q' == c)
			break;
	}
	return 0;
}

The printed result is:
Insert image description here

There are two rows at this time, because scanf brings back the display, the first row is for keyboard input, and the second row is for printing.
Equivalent to the abcq printed by _getch above, there is no first row, only the second row.

Guess you like

Origin blog.csdn.net/kklovecode/article/details/131463828