C++中volatile的作用

来源:互联网 发布:小米网络助手apk通用版 编辑:程序博客网 时间:2024/06/15 05:06

转自:http://www.examda.com/ncre2/C/fudao/20081215/083633612.html以及http://hi.baidu.com/zhuzhenping/blog/item/094ceb09e5a41980d1581bf5.html

volatile的语法和const的是一样的,但是volatile的意思是“在编译器认识的范围外,这个数据可以改变”。环境正在改变数据(可能通过多任务、多线程或者中断处理),所以,volatile告诉编译器不要擅自做出有关该数据的任何假定,优化期间尤其如此。

volatile的本意是一般有两种说法--1.“暂态的”;2.“易变的”。
  其实Volatile是由于编译器优化所造成的一个Bug而引入的关键字。
  int a = 10;
  int b = a;
  int c = a;
  理论上来讲每次使用a的时候都应该从a的地址来读取变量值,但是这存在一个效率问题,就是每次使用a都要去内存中取变量值,然后再通过系统总线传到CPU处理,这样开销会很大。所以那些编译器优化者故作聪明,把a读进CPU的cache里,像上面的代码,假如a在赋值期间没有被改变,就直接从CPU的cache里取a的副本来进行赋值。但是bug也显而易见,当a在赋给b之后,可能a已经被另一个线程改变而重新写回了内存,但这个线程并不知道,依旧按照原来的计划从CPU的cache里读a的副本进来赋值给c,结果不幸发生了。
  于是编译器的开发者为了补救这一bug,提供了一个Volatile让开发人员为他们的过失埋单,或者说提供给开发人员了一个选择效率的权利。当变量加上了Volatile时,编译器就老老实实的每次都从内存中读取这个变量值,否则就还按照优化的方案从cache里读。

volotile -->该变量为一个共享变量,也就是说会有除了本程序之外的其他途径对其值进行更改,如多线程,或是其他的运行程序.
也就是防止编译器对其进行优化而造成不必要的麻烦
一般与const一起用在某些变量的定义中,如const volatile unsigned char *port=0x30

const volatile禁止编译器优化,所谓编译器优化是指当一个变量被声明为const时,编译器认为该变量在某一段代码(如一个函数)中不会发生改变,就会将该变量存储到CPU的寄存器,从CPU寄存器读写数据的速度要远远快于从内存读取数据。
const volatile禁用了编译器优化,也就是说,不允许将该数据保存到CPU寄存器。
保存到CPU寄存器的变量可能在某些情况下被改编,例如,另一个线程可能会改变该寄存器得值, 这样就会导致你原本以为是const的变量发生了改变,导致了bug。
使用const volatile声明就避免了这种情况。

1、volatile 是保证访问的变量不被编译器优化
比如申请的变量 a = 1; 如果嵌入汇编饶开编译器
将a地址内容1改变掉
而你不加volatile就还是原来的1
如果加了则会保证每次数据均是从a的地址处读出
4、寄存器操作一定要加!   一般的驱动程序里的端口操作也需要加, volatile只是保证你每次取变量地址都是从此变量的源地址取值!   比如声明 一个变量uint16 PortAddress=0x0001;   下面的代码中再也没有对 PortAddress进行赋值,如果没加 volatile,则你每次用PortAddress变量时系统会直接取1, 而不是去PortAddress的地址去取他的值,如果 PortAddress是硬件相关的,则可能会因为硬件的原因把他的值改变了(不再是0x0001),从而造成运行出错!

一句话: 取消编译器对此修饰变量的任何优化, 所有对此数据操作都去相应地址中读写 而不会取自因优化而暂存的寄存器中。

用volatile关键字声明变量,是用来告诉编译器每次对此变量的引用都需要从内存地址中读取,即取消编译器对此变量的优化编译。

没用volatile声明的变量,当某次引用时,被编译器从内存地址中读取到AX寄存器,那么在其后的引用中,如果AX寄存器没有被改编,那么编译器会优化成直接读取AX寄存器。


原创粉丝点击