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;
     }
讲讲我的理解: (欢迎打板子...~~!)

关键在于两个地方:     
 
1. 编译器的优化  (请高手帮我看看下面的理解)

在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;

当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致

当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致

当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致 


举一个不太准确的例子: 

发薪资时,会计每次都把员工叫来登记他们的银行卡号;一次会计为了省事,没有即时登记,用了以前登记的银行卡号;刚好一个员工的银行卡丢了,已挂失该银行卡号;从而造成该员工领不到工资 

员工 -- 原始变量地址 
银行卡号 -- 原始变量在寄存器的备份 


2. 在什么情况下会出现(如1楼所说)

    1). 并行设备的硬件寄存器(如:状态寄存器) 
    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
    3). 多线程应用中被几个任务共享的变量 
    

补充: volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人; 

“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化;

而用volatile定义之后,其实这个变量就不会因外因而变化了,可以放心使用了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2008R2Win7管理九DNS冗余和恢复

2008R2Win7管理九DNS冗余和恢复 本文介绍如何在ad中的主dns崩溃后快速利用备份dns将主dns恢复.以及在主dns完好的时候进行dns冗余备份 本文在file这台服务器上安装好dns角色来作为主dns的备份,安装角色的过程不在详细描述,略过.相信大家都知道了. 本问对拓扑图略有改动,故再次更…

预处理命令中的#和##

在c/c的程序设计中,有的时候不免要实现某些对象转换出相应名字字符串或两对象名直接相连的情况,这时候可采用宏定义中加入#和##分别实现相应功能。下面是摘抄的一段解释。 The # and ## preprocessor operators are used with the #define preprocessor …

【转】DICOM通讯(ACSE->DIMSE->Worklist)

转自:DICOM通讯(ACSE->DIMSE->Worklist) - 知乎 1 DICOM通讯概要介绍 DICOM通讯和TCP IP的设计原理别无二致。从用户数据到网络上传输数据的过程中,要经历多层协议处理,每经一层,就…

DipperRiver.Net通信协议设计

说明名称[长度,单位:字节]包结构Header[10]:包头Body[21?]:包体Header[10]协议头[1]:1字节长度,如0x07协议版本[1]:1字节长度,如0x01Body长度[4]:4字节长度的数字,即Body长度最大支持4G保留[4]:Body[25?]…

winCE改变字库方法

更新系统字库:例如要在 WinCE5.0 加入微软雅黑字体的支持 。 第一步:增加如下注册表 [HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/FontPath] "FontPath""// Windows " ; 字库文件所在目录 [HKEY_LOCAL_MACHINE/SYSTEM/GDI] "…

程序员九重镜界,很老的今天刚刚翻出来

今天下午翻电脑找到这个--程序员九重镜界。很旧的,呵呵。第一重: 在哪本电脑杂志上看见软件工程师这个职业介绍,或者走在大街上看见某某软件培训机构鼓吹培训完就能年薪10万的广告,有些羡慕那些编程序的,自己有些蠢蠢欲…

【转】dicom通讯的工作方式及dicom标准简介!!

转自:dicom通讯的工作方式及dicom标准简介 - assassinx - 博客园 本文主要讲述dicom标准及dicom通讯的工作方式。dicom全称医学数字图像与通讯 其实嘛就两个方面 那就是“存储”跟“通讯”。 文件数据组织方式 网络数据组织方式。文件数据组织方式就是解析静态的di…

XIP与HIVE

我们的Image主要由两部分组成:XIPKERNEL.bin和NK.bin,XIPKERNEL.bin中的东西就是那些WinCE中比较核心的又需要经常加载的一些程序和DLL文件,这些文件会被Boot Loader在刚启动的时候拷贝到RAM中去,这样就可以在RAM中XIP(Excute in …

[Silverlight]16进制颜色转ARGB及Color转Int32

16进制色字符串转ARGB做Web的都喜欢用16进制字符串标识颜色,比如“#F5F5F5”这类的,自然这个到了Silverlight/WPF中就要用ARGB表示:“#FFF5F5F5”(前两位标识Alpha,即透明度)。这在XAML中没有任何问题&…

【转】DICOM通信 - PDU数据包(1)

转自:DICOM通信 - PDU数据包(1)_翼遥君的博客-CSDN博客 DICOM上层协议为DIMSE提供透明的网络数据传输服务,即以上层协议规定的协议数据单元传送接收DIMSE的命令流与数据流。上层协议中制定了上层服务以及协议数据单元(Protocol Data Unit,PD…

windows mobile 编译(生成镜像)提速

windows mobile 编译镜像总是让人难以忍受的耗时,当然我们不能每次修改一点东西就build All一次。 下面是自己工作中积累的【不同情况下使用的编译命令】来加速生成镜像的过程,不排除有错的可能,欢迎指正。 对于修改,一般可以分…

ASP.NET MVC + ADO.NET EF 项目实战(二):设计过程与设计工具

工欲善其事,必先利其器。好的工具能够成倍提升工作效率。ASP.NET MVC和ADO.NET EF也是因为其工具出色而受到欢迎。例如: MVC所提供的View模板工具; MVC所提供的View切换、向导工具; ADO.NET EF提供的模型设计工具; ADO…

【转】DICOM通信 - PDU数据包(2)

转自:DICOM通信 - PDU数据包(2)_翼遥君的博客-CSDN博客 DICOM通信-PDU数据包(1)博客中主要分析了DICOM通信协议的连接协商请求和连接协商应答。 在7个PDU数据包中还有5个数据包,从结构上来看,他们比协议的协商过程要简单明了一些。 这篇博客…

Win CE下编译选项介绍

在WinCE中,在"Build OS”菜单中,我们会看到不同的编译选项: "Sysgen","Build and Sysgen"和"Build and Sysgen current BSP" Sysgen:不用多说,当你在"Catalog&quo…

“启动Word时提示出错,只能用安全模式才能打开”的解决方法

启动Word时提示出错,只能用安全模式才能打开,在这种模式下,一些功能将被禁用。而且,每次启动都会出现这样的提示信息,同事们很多向我求助。提示窗口如下: 于是我采取了以下一些措施: 1、用Offic…

DotNET内存管理与垃圾回收[转]

1. Stack(栈)和Heap(堆)每个线程对应一个stack,线程创建的时候CLR为其创建这个stack,stack主要作用是记录函数的执行情况。值类型变量(函数的参数、局部变量等非成员变量)都分配在st…

WinCE中,环境变量的添加,删除和查询

在WinCE中有很多的环境变量,那么如何设置/删除/查询这些环境变量呢:1. 查询环境变量:当我们在PB里打开或者创建一个工程以后,我们可以在菜单中点 “build”->“Open Release Directory in Build Window”,然后会弹出…

【转】DICOM命令集和数据集解析!!

转自:DICOM命令集和数据集解析 - 微笑的艾米 - 博客园 摘 要:本文通过分析一个典型的DICOM消息,详细地解析了DICOM命令集和数据集的构成方式和其含义。并在此基础上,提出了一种实现DICOM命令集和数据集解析的实施方案&#xff0…

【转】WPF XAML X名称空间详解

转自:WPF XAML X名称空间详解_郎涯技术-CSDN博客 X名称空间里面的成员(如X:Name,X:Class)都是写给XAML编译器看的、用来引导XAML编译器将XAML代码编译为CLR代码。 【X名称空间里面到底都有些什么】 x名称空间映射的是:http://schemas.microsoft.com/winfx/2006/xam…

C++编绎器编绎C语言的问题

由于应用的需要,要在原来的C语言中加入C类,这时就会出现很多类型转换的错误,因为在C语言中默认的是强制转换的,而在C中不会自动强制转换,只能手工强制转化。所以出现错误了,只有一个错误一个错误的改了。我…