volatile原理

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的地址处读出
2、寄存器操作一定要加! 一般的驱动程序里的端口操作也需要加, volatile只是保证你每次取变量地址都是从此变量的源地址取值! 比如声明 一个变量uint16 PortAddress=0x0001; 下面的代码中再也没有对 PortAddress进行赋值,如果没加 volatile,则你每次用PortAddress变量时系统会直接取1, 而不是去PortAddress的地址去取他的值,如果 PortAddress是硬件相关的,则可能会因为硬件的原因把他的值改变了(不再是0x0001),从而造成运行出错!
一句话: 取消编译器对此修饰变量的任何优化, 所有对此数据操作都去相应地址中读写 而不会取自因优化而暂存的寄存器中。
用volatile关键字声明变量,是用来告诉编译器每次对此变量的引用都需要从内存地址中读取,即取消编译器对此变量的优化编译。
没用volatile声明的变量,当某次引用时,被编译器从内存地址中读取到AX寄存器,那么在其后的引用中,如果AX寄存器没有被改编,那么编译器会优化成直接读取AX寄存器。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值