探究printf的现象
我们分别在windows系统和linux系统上使用代码做以下操作: 输出"HelloWorld"十次,每次输出后暂停500毫秒。
windows系统上的代码
代码语言:javascript复制#include <stdio.h>
#include <windows.h>
int main()
{
for (int i = 0; i < 10; i ) {
printf("Hello World %dn", i);
Sleep(500);
}
return 0;
}
使用windows.h头文件中提供的Sleep
函数,每次输出后休眠500毫秒。
表现
windows系统上打印出一个HelloWorld后,休眠500毫秒,再打印下一个。
linux系统上的代码
代码语言:javascript复制#include <stdio.h>
#include <unistd.h>
int main()
{
for (int i = 0; i < 10; i ) {
printf("Hello World %dn", i);
usleep(1000*500);
}
return 0;
}
在linux系统上,我们使用unistd.h
头文件中提供的usleep函数,每次输出后休眠500毫秒。usleep的单位为1微秒,1000微秒为1毫秒。代码中给usleep传入1000 * 500,表示500毫秒。
表现
linux系统上,休眠5000毫秒,打印出所有HelloWorld
输入输出缓存区
输出缓存区
在向控制台打印字符时,程序会先将需要打印的字符串放在输出缓存区中,到特定时刻,再一起显示到控制台。 在计算机中,需要将显示在屏幕上的数据发送至显卡,再由显卡进行显示。显然,累积一串字符再批量处理发送,比起单个单个发送更有效率。
何时刷新输出缓存
我们将缓存中的数据发送至目的地并清空缓存,这一行为称之为刷新缓存
- 在windows系统下,使用printf后,数据被写入到输出缓存区。随后,立即刷新缓存区。
- 在linux系统下,使用printf后,数据被写入到输出缓存区。后续的printf会在缓存区中累积数据。直到程序结束才刷新缓存区。
行(háng)缓存的刷新时机
输入输出缓存属于行缓存,即一行结束后必须刷新缓存。
还有一种缓存形式为完全缓存,这种缓存的形式需要等到整个缓存区被填满,才会刷新缓存。
对于行缓存,如果要刷新缓存,只要将一行结束即可。也就是n
在windows系统中似乎不那么在乎一行字符是否结束。但是在linux下却严格遵循一行字符结束才刷新缓存。
注意
输出缓存是一个系统特性,而不是函数特性。所有输出函数,包括printf,putchar等,均存在输出缓存。
输入缓存区
类似于输出函数(如printf,putchar)存在输出缓存,输入函数(如scanf,getchar)也存在输入缓存。
并且这些输入函数属于阻塞函数,当输入缓存区没有内容时。程序将阻塞在输入函数中,等待用户从键盘键入字符,并按回车确认。
当我们按下了回车键(即换行,存储为n
),输入的字符串将进入输入缓存区
接下来,输入函数将从输入缓存区获取字符,删除缓存区中已获取的字符,并解除阻塞状态继续执行代码。
输入缓存区仍有数据getchar不阻塞
使用getchar读取输入字符串
代码语言:javascript复制#include <stdio.h>
int main()
{
char str[20];
int i = 0;
while (i < 19) {
char c = getchar();
str[i ] = c;
if (c == 'n')
{
break;
}
}
str[i] = '