由于初学者对这两个概念总是有点蒙查查,所以特意在新的教材写了这一节内容。
1.数据缓冲区
我们知道,当用户通过键盘输入数据时,scanf函数只有检测到'\n'符,计算机才认为用户数据输入完毕。而包括回车符在内的数据总得有个落脚点吧!当然,聪明的计算机设计大师绝不会让用户输入的有价值的数据无缘无故地消失掉,他们早已考虑了这些细节问题,事先为这些数据的去处作了充分周密的安排。
与极速运行的CPU相比,数据的输入/输出和键盘的I/O接口是一个极其缓慢的外设。为了减少CPU的等待时间,因此在内存中开辟了一个叫做“缓冲区”的存储单元,用于保存输入或输出数据。“缓冲区”其实相当于一个仓库,其示意图详见图 4.2(略)。
打一个比方,“通过键盘输入数据”好比正在生产产品的工厂,“缓冲区”就像仓库,用于放置已经生产出来的产品,而“读取数据”则好比卖东西的门市部。我们想一想,如果没有仓库,则工厂生产出来的产品就没地方放置,必须生产一个产品,门市部再去取一个产品,然后再生产再取,如果生产10个产品就得来回跑10趟,这样岂不是很浪费资源?于是就有了仓库,工厂不再需要直接和门市部打交道,它只需要将生产好的产品放到仓库就行,而门市部也不需要立即去处理已经生产的产品,当要用的时候再去仓库取就好了。
由此可见,从键盘输入数据存放到缓冲区,即相当于工厂将生产好的产品放到仓库中。而从缓冲区读取数据,即相当于从仓库取走产品。
当scanf函数检测到'\n'符时,则立即从缓冲区中取走输入数据赋值给变量,但却不会取走对用户来说无效的'\n'符。虽然'\n'符用作输入数据结束的标志符,但也可作为每一行源代码结束的标志符。
此时,即使用户第二次执行读取数据操作,而计算机则会直接跳过去,因为缓冲区内只有'\n'符。其实这些可能的不合情理的操作,计算机设计大师犹如神机妙算早已料到,每次都会让计算机检测缓冲区是非为空,只有缓冲区不空时,才允许执行读取数据操作。
2. 变量的地址
虽然“缓冲区”这个名字对于初学者来说是第一次接触,但实际上它仅仅是一个“中转站”而已,因此也不需要知道保存这些数据的存储单元地址。而变量则不一样,它在内存中必须具有确定的位置,否则无法一直保存以备再次使用。那么到底如何获得变量的地址呢?C语言用“&num(&地址运算符加变量名)”的方式获得变量的地址。比如:
int num = 1;
定义了一个整型值变量num并初始化为1。
通过前面的学习,我们知道,num是变量名,变量num的值为1,那么保存数值1的变量的地址就是“&num”。也就是说,从缓冲区读取的数据赋值给变量保存在“&num”存储单元中。
而事实上,几乎所有的C 程序都包含输入输出,因此输入输出是程序中最基本的操作之一。从程序清单 2.2开始可以看到,输入并读取整数的操作为
scanf("%d",&num);
即就是将从键盘输入的数据存放到缓冲区,当检测到'\n'符时,则立即从缓冲区读取数据赋值给变量num。
3.输入函数格式
用scanf函数输入数据的一般形式如下:
scanf(格式控制,地址表列);
“格式控制”与printf函数完全相同,它同样包括“格式声明和普通字符”信息。而“地址表列”则是由若干个地址所组成的表列,因此既可为变量的地址,也可为字符串的首地址。
......