c/c++中register关键字(寄存器、缓存、内存)

一般情况下,变量的值是存储在内存中的,CPU 每次使用数据都要从内存中读取。如果有一些变量使用非常频繁,从内存中读取就会消耗很多时间,例如 for 循环中的增量控制:
    
    
  1. int i;
  2. for(i=0; i<1000; i++){
  3. // Some Code
  4. }
int i;
for(i=0; i<1000; i++){
    // Some Code
}
执行这段代码,CPU 为了获得 i,会读取 1000 次内存。

为了解决这个问题,可以将使用频繁的变量放在CPU的通用寄存器中,这样使用该变量时就不必访问内存,直接从寄存器中读取,大大提高程序的运行效率。

寄存器、缓存、内存

为了加深对 register 变量的理解,这里有必要讲一下CPU寄存器。

按照与CPU的远近来分,离CPU最近的是寄存器,然后是缓存,最后是内存。

寄存器是最贴近CPU的,而且CPU只在寄存器中进行存取。寄存的意思是暂时存放数据,不用每次都从内存中取,它是一个临时的存放数据的空间。

而寄存器的数据又来源于内存,于是 CPU <-- 寄存器 <-- 内存,这就是它们之间的信息交换。

那么为什么还需要缓存呢?因为如果频繁地操作内存中同一地址上的数据会影响速度,于是就在寄存器和内存之间设置一个缓存,把使用频繁的数据暂时保存到缓存,如果寄存器需要读取内存中同一地址上的数据,就不用大老远地再去访问内存,直接从缓存中读取即可。

缓存的速度远高于内存,价格也是如此。

注意:缓存的容量是有限的,寄存器只能从缓存中读取到部分数据,对于使用不是很频繁的数据,会绕过缓存,直接到内存中读取。所以不是每次都能从缓存中得到数据,这就是缓存的命中率,能够从缓存中读取就命中,否则就没命中。

关于缓存的命中率又是一门学问,哪些数据保留在缓存,哪些数据不保留,都有复杂的算法。

在这里插入图片描述

注意:上面所说的CPU是指CPU核心,从市场上购买的CPU已是封装好的套件,附带了寄存器和缓存,插到主板上就可以用。

从经济和速度的综合考虑,缓存又被分为一级缓存、二级缓存和三级缓存,它们的存取速度和价格依次降低,容量依次增加。购买到的CPU一般会标出三级缓存的容量。

register 变量

寄存器的数量是有限的,通常是把使用最频繁的变量定义为 register 的。
来看一个计算 π 的近似值的例子,求解的一个近似公式如下:

在这里插入图片描述


为了提高精度,循环的次数越多越好,可以将循环的增量控制定义为寄存器变量,如下所示:

   
   
  1. #include <stdio.h>
  2. #include <conio.h>
  3.  
  4. int main()
  5. {
  6. register int i = 0; // 寄存器变量
  7. double sign = 1.0, res = 0, ad = 1.0;
  8.  
  9. for(i=1; i<=100000000; i++)
  10. {
  11. res += ad;
  12. sign=-sign;
  13. ad=sign/(2*i+1);
  14. }
  15.  
  16. res *= 4;
  17. printf("pi is %f", res);
  18.  
  19. getch();
  20. return 0;
  21. }
#include <stdio.h>
#include <conio.h>

int main()
{
register int i = 0; // 寄存器变量
double sign = 1.0, res = 0, ad = 1.0;

for(i=1; i&lt;=100000000; i++)
{
    res += ad;
    sign=-sign;
    ad=sign/(2*i+1);
}

res *= 4;
printf("pi is %f", res);

getch();
return 0;

}
运行结果:

pi is 3.141593



关于寄存器变量有以下事项需要注意:

  1. 为寄存器变量分配寄存器是动态完成的,因此,只有局部变量和形式参数才能定义为寄存器变量。


  2. 局部静态变量不能定义为寄存器变量,因为一个变量只能声明为一种存储类别。


  3. 寄存器的长度一般和机器的字长一致,所以,只有较短的类型如int、char、short等才适合定义为寄存器变量,诸如double等较大的类型,不推荐将其定义为寄存器类型。


  4. CPU的寄存器数目有限,因此,即使定义了寄存器变量,编译器可能并不真正为其分配寄存器,而是将其当做普通的auto变量来对待,为其分配栈内存。当然,有些优秀的编译器,能自动识别使用频繁的变量,如循环控制变量等,在有可用的寄存器时,即使没有使用 register 关键字,也自动为其分配寄存器,无须由程序员来指定。

c++中register:

在早期c语言编译器不会对代码进行优化,因此使用register关键字修饰变量是很好的补充,大大提高的速度。

register关键字请求让编译器将变量a直接放入寄存器里面,以提高读取速度,在C语言中register关键字修饰的变量不可以被取地址,但是c++中进行了优化。

c++中依然支持register关键字,但是c++编译器也有自己的优化方式,即某些变量不用register关键字进行修饰,编译器也会将多次连续使用的变量优化放入寄存器中,例如入for循环的循环变量i。

c++中也可以对register修饰的变量取地址,不过c++编译器发现程序中需要取register关键字修饰的变量的地址时,register关键字的声明将变得无效

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值