知识库之volatile关键字
来源:互联网 发布:mac精确模式怎么退出 编辑:程序博客网 时间:2024/05/15 02:07
一. volatile的定义
一个定义为volatile的变量是说这变量可能会被意想不到的改变,这样编译器就不会去假设这个变量的值了。准确的说是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器的备份。
也许,大家还不是很理解,volatile到底有什么用,别急,且听慢慢道来。
1)由于访问寄存器的速度要快于RAM,因此,编译器一般会做减少存取外部RAM的优化;
2)编译器使用一种技术名叫数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并、常量传播等优化。
这样,当变量在定义和使用之间的代码没有改变此变量值时,其值可能保存到某个寄存器中,当使用时,直接从寄存器中取值,而不去内存中取值,这就是编译器优化代码的结果。
二. volatile的作用
volatile是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等,volatile对应的变量可能在你的程序本身不知道的情况下发生改变,比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量,你自己的程序,是无法判定何时这个变量会发生变化;还比如,此变量和一个外部设备的某个状态对应,当外部设备发生操作的时候,通过驱动程序和中断事件,系统改变了这个变量的数值,而你的程序并不知道。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
volatile字面解释为“易变的”,但其实不准确,其易变是因为外在因素引起的,如多线程、中断等(即不被程序指明的方式改变),被voliate修饰的变量在存取时都会重新读取内存的值,所以volatile应该理解为“直接存取原始内存地址”。
三. volatile的适用范围
一般在嵌入式程序开发中常用。其适用的实例如下:
1)并行设备的硬件寄存器(如,状态寄存器)
2)一个中断服务子程序中会访问到的非自动变量,或者说中断服务子程序中修改的供其他程序检测或适用的变量
3)多线程应用中被几个任务共享的变量
上面1)说的情形暂未遇到过,暂且不谈;
上面2)说的情形,如下,程序本意是希望ISR_2中断产生时,在main中调用dosomething()函数,但由于编译器判断在main中没有修改过i,因此可能只执行一次对i从内存读取到某个寄存器中,然后每次if判断都只使用这个寄存器里面的“副本”,导致dosomething()永远不会执行,但在i前加上volatile修饰,则编译器保证对此变量的读写都会对其对应的内存进行:
static int i = 0;int main(void){ ... while(1) { if(i) dosomething(); }}/*interrupt service routine*/void ISR_2(void){ i = 1;}上面说的3)解释如下:
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变,它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b= *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
对1)2)问题的另一种解释:
volatile修饰符告诉complier变量值可以以任何不被程序明确指明的方式改变,最常见的例子就是外部端口的值,它的变化可以不用程序内的任何赋值语句就有可能改变的,这种变量就可以用volatile来修饰,complier不会优化掉它。const修饰的变量在程序里面是不能改变的,但是可以被程序外的东西修改,就象上面说的外部端口的值,如果仅仅使用const,有可能complier会优化掉这些变量,加上volatile就万无一失了。所以使用const
例如const
- 知识库之volatile关键字
- c++关键字之volatile
- C关键字之 volatile
- C++之关键字volatile
- 关键字之volatile
- 多线程之volatile关键字
- c++关键字之:volatile
- Java之Volatile关键字
- 多线程之volatile关键字
- JAVA关键字之volatile
- C++关键字之volatile
- Java 之 volatile关键字
- java之volatile关键字
- 多线程之volatile关键字
- Java-理论知识之关键字Volatile
- JAVA 多线程之~~volatile关键字
- java学习之关键字volatile
- 线程同步之volatile关键字
- 结构化数据和非结构化数据
- JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载
- SDJZU-电子钟
- POJ 3264 RMQ
- octave隐函数如何作图
- 知识库之volatile关键字
- 子集生成算法
- 好东西Bootstrap
- [leetcode]Jump Game II
- Unable to locate appropriate constructor on class
- SDJZU-放大的X
- iptables学习 02 SNAT
- phpunit入门基础
- 字符流