5.1.4 寄存器变量
通过前面的介绍,我们知道变量在一般情况下都是存在内存中的。如果程序需要使用某个变量,CPU的控制器将通过一定的寻址方式从内存中获取值,而后再做进一步处理。CPU的控制器从内存中取得变量值后会将其暂存在寄存器中。通过前面的学习我们知道,寄存器就是CPU自己的"小内存",它的特点是"容量小、速度快"。在正常情况下,编程语言本身是无法直接操作寄存器的。但某些时候,一些变量有可能会被频繁地使用到,这时,频繁地对内存进行存取操作就有可能耗用较多的时间;如果我们能够有效地将CPU的寄存器利用起来,就会有效地提升程序的运行效率。
C语言中使用关键字register来声明局部变量为寄存器变量。寄存器变量的值会被存放在CPU的寄存器中,每当需要使用它们时,CPU就可以直接使用,而无须再通过控制器从内存中获取。由于操作寄存器的速度远高于操作内存,所以正确地使用寄存器变量能够有效地提高程序运行效率。
下面给出了一段使用寄存器变量的示例程序。
- #include"stdio.h"
-
- int fun(int n)
- {
- register int sum = 0;
- for(int i = 1; i <= n; i++)
- sum += i;
- return sum;
- }
-
- void main()
- {
- int result = 0;
- result = fun(1000);
- printf("sum(1000) = %d\n", result);
- }
使用寄存器变量使不是真的使程序的运行速度提高了呢?通过一个简单的实验就能回答这个问题,但是由于本书目前还没有介绍到这方面的知识,所以这个实验暂时无法进行。如果读者阅读了本书的第9章,那么就可以使用第9章中所介绍的技术来实际评估一下上述程序通过使用寄存器变量而获得的性能改进情况到底如何。
使用寄存器变量需要注意以下一些问题。
首先,读者必须明确只有局部自动变量和形式参数才能够被定义为寄存器变量,全局变量和局部静态变量都不能被定义为寄存器变量。所以,如"register static int a;"这样的语句就是错误的!这很容易解释,全局变量和局部静态变量都被放在静态存储区中,而寄存器变量被放在寄存器中,一个变量当然只能选择两种存放方式中的一种。
其次,一个计算机系统中的寄存器数量是有限的,因此不能定义任意多个寄存器变量。而且对于不同的系统来说,所允许使用的最大寄存器数量也是不同的。上一节中我们就介绍过,在Intel体系中CPU所具有的寄存器个数在6~16个之间,而其他体系的CPU所具有的寄存器数量可能更多。不同系统上的寄存器数量可能不同,所以在编程时所允许使用的寄存器数量也会不同。另外,不同系统对于寄存器变量的处理方式也可能不同,有的系统只允许将 int、char和指针型变量定义为寄存器变量,而有的系统则将寄存器变量当作自动变量来看,并不真正把它们存放在寄存器中。
正如上一小节中所说的那样,经过多年的发展,编译器已经可以非常智能地进行许多优化工作了,特别是在程序优化上,编译器已经比大多数人做得更好了。目前的编译器在这方面也有所考虑,它们基本上可以识别出那些会被频繁使用的变量,对于这些变量编译器就会把它们存放在寄存器中,而不需要程序员在代码中显式地指定。所以寄存器变量的声明从某种程度上来说并不是必需的,读者仅对此有所知悉即可。这里只是想借C语言中的寄存器变量这种语法技术来证明一个事实,即操作寄存器的速度的确高于操作内存。