Chinaunix首页 | 论坛 | 博客
  • 博客访问: 867994
  • 博文数量: 82
  • 博客积分: 2283
  • 博客等级: 大尉
  • 技术积分: 2007
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-15 22:19
文章分类

全部博文(82)

文章存档

2012年(82)

分类: C/C++

2012-08-01 16:03:02

volatile——C++关键字
volatile的本意是“易变的” 由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化,但有可能会读脏数据。当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。

精确地说就是,优化器在用到这个变量时必须每次都小心地重新从内存里读取这个变量的值,而不是使用保存在寄存器里的备份。 下面是volatile变量的几个例子:

1) 并行设备的硬件寄存器(如:状态寄存器)

2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3) 多线程应用中被几个任务共享的变量

在这里要说下,其实不仅仅是并行设备的硬件寄存器,串行设备的硬件寄存器也行,也就是说只要是硬件寄存器都需要这么做,当我们不能确保寄存器里的值一定 不会变的情况下就需要使用volatile。看下面的例子,2410addr.h是所有寄存器中的头文件,其中就有很多volatile的应用,下面列出 一个宏定义出来:

#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer

这个就是串行的接收buffer,其地址为0x50000024,如果我们没有将这个地址强行转换成volatile,那么我们在使用rURXH0时, 可能直接从cpu的寄存器中取值。因为之前rURXH0被访问过,也就是说之前就从内存中取出rURXH0的值保存到 某个寄存器中。之所以直接从寄存器中取值,而不去内存中取值,是因为编译器优化代码的结果(访问cpu寄存器比访问ram快的多)。用volatile关 键字对0x50000024进行强制转换,使得每一次被访问rURXH0时,执行部件都会从0x50000024这个内存单元中取出值来赋值给 rURXH0。

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如 果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。所以遇 到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

一般说来,volatile用在如下的几个地方:

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
阅读(2598) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~