一、意义:

该关键字的意义就是表示定义的变量值随时都会改变,必须从变量的地址处读取值,所以只有这个变量在使用过程中可能被改变(比如中断程序),就需要用这个关键字说明。

)volatile,关键字volatile 确保本条指令不会因C 编译器的优化而被省略,且要求每次直接读值。

)共享的内存地址,多个程序都对它操作的时候。你的程序并不知道,这个内存何时被改变了。如果不加这个voliatile修饰,程序是利用catch当中的数据,那个可能是过时的了,加了 voliatile,就在需要用的时候,程序重新去那个地址去提取,保证是最新的

—————————————————————————————————————

二、使用场景

volatile 主要用于变量会异步改变的情况下,主要有三个方面

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

 2)  . 中断和主循环都会用到的全局变量 

).操作系统中的线程间都会用到的公共变量.

———————————————————————————————————

三、嵌入式编程中经常用到 volatile这个关键字,下面是两种用法的例子:[1]

1):告诉compiler不能做任何优化

比如,要往某一地址送两指令:

int *ip =...; //设备地址

*ip = 1; //第一个指令

*ip = 2; //第二个指令

以上程序compiler可能做优化而成:

int *ip = ...;
*ip = 2;
结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意:

volatile int *ip = ...;
*ip = 1;
*ip = 2;
即使你要compiler做优化,它也不会把两次付值语句间化为一。它只能做其它的优化。这对device driver程序员很有用。

   
 

再比如:[2]

XBYTE[2]=0x55;

XBYTE[2]=0x56;

XBYTE[2]=0x57;

XBYTE[2]=0x58;

如果对外部硬件上述四条语句分别表示不同的操作,会产生四种不同的动作,那么编译器就不能像对待纯粹的程序那样对上述四条语句进行优化只认为XBYTE[2]=0x58,而忽略前三条语句,并且只产生1条机器码。如果XBYTE用volatileo修饰过,此时编译器会逐一的进行编译并产生相应的4条机器码。

      
 

2):表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。

如 volatile char a;
a=0;
while(!a){
//do some things;
}
doother();
如果没有 volatile doother()不会被执行

   
 

四、

  1. volatile与const

volatile和const一起用,没有冲突,const针对本程序而言,保证该值不变;volatile应付其他情况(如多线程,中断),避免优化后出现错误。

   
 

  1. volatile与指针 

volatile修饰指针一般用在共享指针上面。

   
 

下面代码:

uchar * volatile reg;
行代码里volatile修饰的是reg这个变量。所以这里实际上是定义了一个uchar类型的指针,并且这个指针变量本身是volatile 的。但是指针所指的内容并不是volatile的!在实际使用的时候,编译器对代码中指针变量reg本身的操作不会进行优化,但是对reg所指的内容 reg却会作为non-volatile内容处理,对reg的操作还是会被优化。通常这种写法一般用在对共享指针的声明上,即这个指针变量有可能会被中断等函数修改。将其定义为volatile以后,编译器每次取指针变量的值的时候都会从内存中载入,这样即使这个变量已经被别的程序修改了当前函数用的时候也能得到修改后的值(否则通常只在函数开始取一次放在寄存器里,以后就一直使用寄存器内的副本)。

需要注意将上述代码与下面的代码进行区别

volatile uchar *reg;
这行代码里volatile修饰的是指针所指的内容。所以这里定义了一个uchar类型的指针,并且这个指针指向的是一个volatile的对象。但是指针变量本身并不是volatile的。如果对指针变量reg本身进行计算或者赋值等操作,是可能会被编译器优化的。但是对reg所指向的内容 reg的引用却禁止编译器优化。因为这个指针所指的是一个volatile的对象,所以编译器必须保证对reg的操作都不被优化。通常在驱动程序的开发中,对硬件寄存器指针的定义,都应该采用这种形式


volatile uchar * volatile reg;
这样定义出来的指针就本身是个volatile的变量,又指向了volatile的数据内容。

 

五、例子:

1)2440里头文件对寄存器地址的定义就是volatile

     #define rBWSCON (*(volatile unsigned *)0x48000000) //Bus width & wait status

)中断程序:

http://www.ednchina.com/ART_58640_29_0_OA_c6686e7a.HTM

如果一个变量会被其它引用改变,或在其它并行的任务中会被改变(例如中断服务程序),都要显式地说明为"volatile",否则在编译器优化阶段会作出错误的判断,例如将这个变量读入寄存器以后,在没有对这个变量赋值以前,会一直使用寄存器中的值,而实际上这个变量的值可能已经被一个指针引用改变了,或者是在中断服务程序中被改变了,下面这个例子说明这种错误:

 

  正确的写法应该是将第一句改为:volatile unsigned char cnt;

  需要注意:作为一个健壮的程序,一定要注意volatile的用法,否则即使能得到正确结果,也会给程序移植或升级带来意想不到的问题。

 

引用:

1. volatile与指针
http://blog.csdn.net/turkeyzhou/article/details/8953911 

参考:

1、C中的volatile用法 http://www.cnblogs.com/chio/archive/2007/11/24/970632.html

2、Volatile相关知识 http://www.100ask.org/bbs/forum.php?mod=viewthread&tid=3902&highlight=volatile

    

c语言,volatile的更多相关文章

  1. C语言volatile关键字

    volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据.如果没有volatile关键字,则编译器可能优化读取和存储 ...

  2. C语言volatile关键字-漫画(转)

    转载地址:https://zhuanlan.zhihu.com/p/56191979 ————— 第二天 ————— ———————————— Java内存模型简称JMM(Java Memory Mo ...

  3. C语言---volatile(我的工程笔记本)

    一般说来,volatile用在如下的几个地方: 1.中断服务程序中修改的供其它程序检测的变量需要加volatile: 2.多任务环境下各任务间共享的标志应该加volatile: 3.存储器映射的硬件寄 ...

  4. C语言学习及应用笔记之四:C语言volatile关键字及其使用

    在C语言中,还有一个并不经常使用但却非常有用的关键字volatile.那么使用volatile关键字究竟能干什么呢?接下来我将就此问题进行讨论. 一个使用volatile关键字定义变量,其实就是告诉编 ...

  5. C语言volatile关键字的用法

    volatile关键字的意义在于让被关键字修饰的变量每次使用时都重新去主内存里读取变量,而不是从高速缓存去读取. int a = 1; 普通变量定义之后,若要使用它,都会 先把它的值从主内存拷贝到高速 ...

  6. c 语言 volatile 关键字

    一.前言 1.编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问.另外在现代CPU中指令的执行并不一定严格按照顺序执行,没 ...

  7. C语言volatile

    原文地址: http://www.cnblogs.com/yc_sunniwell/archive/2010/06/24/1764231.html volatile提醒编译器它后面所定义的变量随时都有 ...

  8. 浅述 Java 并发

    浅述 Java 并发 volatile volatile只能保证变量对各个线程的可见性,但不能保证原子性.关于 Java语言 volatile 的使用方法就不多说了,我的建议是 除了 配合packag ...

  9. Java 原子语义同步的底层实现

    原子语义同步的底层实现 volatile volatile只能保证变量对各个线程的可见性,但不能保证原子性.关于 Java语言 volatile 的使用方法就不多说了,我的建议是 除了 配合packa ...

  10. [汇编与C语言关系]5. volatile限定符

    现在研究一下编译器优化会对生成的指令产生什么影响,在此基础上介绍C语言的volatile限定符.首先看下面的C程序: /* artificial device registers */ unsigne ...

随机推荐

  1. CXF 开发 WebService

    什么是CXF: Apache CXF = Celtix + Xfire 支持多种协议: SOAP1.1,1.2 XML/HTTP CORBA(Common Object Request Broker ...

  2. Centon6.5虚拟机桥接设置

    参考资料:http://blog.csdn.net/iamfafa/article/details/6209009 安装虚拟机的时候 就直接选择桥接,可以直接 使用 查看此状态下的配置如下 : 虚拟环 ...

  3. jquery-1.10.2.min.js之Multiple markers at this line

    1.windows-preferences  输入validation 2. 点击进入  3. 将JavaScript validator for js files 的两个对勾去了就OK!     4 ...

  4. poco vs Boost

    Wooce Yang收集整理 POCO的优点: 1) 比boost更好的线程库,特别是一个活动的方法的实现,并且还可设置线程的优先级. 2) 比 boost:asio更全面的网络库.但是boost:a ...

  5. 第二种:NSObject

    - (void)viewDidLoad { [super viewDidLoad]; /** * 开启子线程的方式之一:NSObject */ // 第一个参数:selector // 第二个参数:方 ...

  6. 【JUnit4.10源码分析】5 Statement

    假设要评选JUnit中最最重要的类型.或者说核心,无疑是org.junit.runners.model.Statement.Runner等类型看起来热闹而已. package org.junit.ru ...

  7. BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec   Memory Limit: 256 MB Submit: 123   Solved: 73 [ Submit][ St ...

  8. iOS中的图像处理(一)——基础滤镜

    最近在稍微做一些整理,翻起这部分的代码,发现是两个多月前的了. 这里讨论的是基于RGBA模型下的图像处理,即将变换作用在每个像素上. 代码是以UIImage的category形式存在的: typede ...

  9. android软键盘enter键

    enter键,回车键,电脑键盘上enter键就有多种响应.android软键盘也不例外 你在EditText上输入以后,想在下一行输入框输入,可能需要去点击下一行输入框,让它获取焦点,也可能要隐藏软键 ...

  10. Mirantis OpenStack HA

    Mysql使用Galera做Active/Active集群,同时使用Pacemaker,因为Galera mysql用到了领导机选举机制quorum,所以控制节点至少三个 RabbitMQ使用mirr ...