C中的volatile用法
.volatile的本质:
1> 编译器的优化
在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。
当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。
当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。
2>volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。
例如:
volatile int i=10;
int j = i;
...
int k = i;
volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。
而
优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果
i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。
/**********************
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3) 多线程应用中被几个任务共享的变量
回
答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,
所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将
稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
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;
}
位操作(Bit manipulation)
//*********************
嵌入式编程中经常用到 volatile这个关键字,在网上查了下他的用法可以归结为以下两点:
一:告诉compiler不能做任何优化
比如要往某一地址送两指令:
int *ip =...; //设备地址
*ip = 1; //第一个指令
*ip = 2; //第二个指令
以上程序compiler可能做优化而成:
int *ip = ...;
*ip = 2;
结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意:
volatile int *ip = ...;
*ip = 1;
*ip = 2;
即使你要compiler做优化,它也不会把两次付值语句间化为一。它只能做其它的优化。这对device driver程序员很有用。
二:表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。
如 volatile char a;
a=0;
while(!a){
//do some things;
}
doother();
如果没有 volatile doother()不会被执行
C中的volatile用法的更多相关文章
- C#中的volatile用法
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进 ...
- C中的volatile用法[转载]
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进 ...
- (转)C中的volatile用法
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进 ...
- zz剖析为什么在多核多线程程序中要慎用volatile关键字?
[摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...
- java中的Volatile 变量
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...
- C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI
目录 1. 前言2 2. 结论2 3. volatile应用场景3 4. 内存屏障(Memory Barrier)4 5. setjmp和longjmp4 1) 结果1(非优化编译:g++ -g -o ...
- 深入理解Java中的volatile关键字
在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...
- java中的Volatile关键字使用
文章目录 什么时候使用volatile Happens-Before java中的Volatile关键字使用 在本文中,我们会介绍java中的一个关键字volatile. volatile的中文意思是 ...
- [转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法
一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBo ...
随机推荐
- Amoeba For MySQL读写分离
Amoeba安装,参考http://hi.baidu.com/itfenqing/item/79fe989838e1e8ad83d2959c Amoeba版本为:amoeba-mysql-1.3.1- ...
- 【微信开发】 新浪SAE开发平台 注意事项
1. 微信开发 新浪SAE开发平台 验证Token 一直失败? 这个问题困扰了一个又一个的微信学习者,现在百度到的答案有:在echo $echoStr;之前添加header('content-type ...
- jfinal路由简单解析
在jfinal中,通过JFinalFilter对所有的类进行过滤. 以下是路由的调用关系(我在调用关系旁边做了标记,会贴出具体的代码和解释): -1- Config: Routes -2- Inter ...
- 整理常用的iOS第三方资源
一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地址:https://github. ...
- tcpdump教程入门
tcpdump是一个最基本重要的网络分析工具, 掌握好这, 对于学习tcp/ip协议也是很有帮助的. 理解了tcp/ip协议栈的知识, 分析调优网络的能力才会更高. 所以使用tcpdump相比其它的工 ...
- (转)PHP常用函数
来源 :http://www.cnblogs.com/dreamhome/archive/2011/05/04/2037011.html ---------------------------- & ...
- ubuntu之使用sublime text3搭建Python IDE
参考文章: 教你如何将 Sublime 3 打造成 Python/Django IDE开发利器 Ubuntu16.04下使用sublime text3搭建Python IDE 如何优雅地使用Subli ...
- SQL2012新特性一次一个数据块----特殊的查询分页
对于数据库人员来说,在软件项目开发的过程中,或多或少的不可避免的就是经常遇到类似“UI查询结果设计”这样的说法,当听到UI设计的时候,多数人的第一反应是“靠!关我毛事!~这是其他人的问题!”. 然而, ...
- 获取dll中根目录
AppDomain.CurrentDomain.BaseDirectory获取当前应用程序域的基目录 好像是万能的:form:可执行文件路径控制台:输出路径web:根目录
- Linux基础命令介绍七:网络传输与安全 wget curl rsync iptables
本篇接着介绍网络相关命令:wget 文件下载工具.curl 网络数据传输工具.rsync 文件传输工具等. 本篇接着介绍网络相关命令 1.wget 文件下载工具 wget [option]... [U ...