IT专家为什么C中需要挥发物.docx

上传人:b****4 文档编号:3461811 上传时间:2022-11-23 格式:DOCX 页数:20 大小:26.92KB
下载 相关 举报
IT专家为什么C中需要挥发物.docx_第1页
第1页 / 共20页
IT专家为什么C中需要挥发物.docx_第2页
第2页 / 共20页
IT专家为什么C中需要挥发物.docx_第3页
第3页 / 共20页
IT专家为什么C中需要挥发物.docx_第4页
第4页 / 共20页
IT专家为什么C中需要挥发物.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

IT专家为什么C中需要挥发物.docx

《IT专家为什么C中需要挥发物.docx》由会员分享,可在线阅读,更多相关《IT专家为什么C中需要挥发物.docx(20页珍藏版)》请在冰豆网上搜索。

IT专家为什么C中需要挥发物.docx

IT专家为什么C中需要挥发物

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

为什么C中需要挥发物?

WhyisvolatileneededinC?

Whatisitusedfor?

Whatwillitdo?

 为什么C中需要挥发物?

它的用途是什么?

它会做什么?

 316

 Volatiletellsthecompilernottooptimizeanythingthathastodowiththevolatile

variable.

 Volatile告诉编译器不要优化与Volatile变量有关的任何东西。

 Thereisonlyonereasontouseit:

Whenyouinterfacewithhardware.

 使用它只有一个原因:

当您与硬件交互时。

 Let’ssayyouhavealittlepieceofhardwarethatismappedintoRAMsomewhereand

thathastwoaddresses:

acommandportandadataport:

 假设你有一小块硬件被映射到某个地方的RAM中它有两个地址:

一个命令端口和

一个数据端口:

 typedefstructintcommand;intdata;intisbusy;}MyHardwareGadget;Nowyouwant

tosendsomecommand:

 现在你想发送一些命令:

 voidSendCommand(MyHardwareGadget*gadget,intcommand,intdata)//wait

whilethegadgetisbusy:

while(gadget-isbusy)//donothinghere.//setdatafirst:

gadget-

data=data;//writingthecommandstartstheaction:

gadget-command=command;

Lookseasy,butitcanfailbecausethecompilerisfreetochangetheorderinwhichdata

andcommandsarewritten.Thiswouldcauseourlittlegadgettoissuecommandswiththe

previousdata-value.Alsotakealookatthewaitwhilebusyloop.Thatonewillbe

optimizedout.Thecompilerwilltrytobeclever,readthevalueofisbusyjustonceand

thengointoaninfiniteloop.That’snotwhatyouwant.

 看起来很简单,但它可能会失败,因为编译器可以自由更改数据和命令的顺序。

这将导致我们的小工具使用前面的数据值发出命令。

还可以查看“忙循环”时的等

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

待。

这个会被优化。

编译器将尝试聪明一点,只读一次isbusy的值,然后进入一个

无限循环。

那不是你想要的。

 Thewaytogetaroundthisistodeclarethepointergadgetasvolatile.Thiswaythe

compilerisforcedtodowhatyouwrote.Itcan’tremovethememoryassignments,itcan’t

cachevariablesinregistersanditcan’tchangetheorderofassignmentseither:

 解决这个问题的方法是将指针小部件声明为volatile。

这样,编译器就被迫执行您

所编写的操作。

它不能删除内存分配,不能缓存寄存器中的变量,也不能改变分配

的顺序:

 Thisisthecorrectversion:

 这是正确的版本:

 voidSendCommand(volatileMyHardwareGadget*gadget,intcommand,intdata)//

waitwhilethegadgetisbusy:

while(gadget-isbusy)//donothinghere.//setdatafirst:

gadget-data=data;//writingthecommandstartstheaction:

gadget-command=

command;147

 Anotheruseforvolatileissignalhandlers.Ifyouhavecodelikethis:

 volatile的另一个用途是信号处理程序。

如果你有这样的代码:

 quit=0;while(!

quit)/*verysmallloopwhichiscompletelyvisibletothecompiler*/

Thecompilerisallowedtonoticetheloopbodydoesnottouchthequitvariableand

convertthelooptoawhile(true)loop.Evenifthequitvariableissetonthesignalhandler

forSIGINTandSIGTERM;thecompilerhasnowaytoknowthat.

 编译器可以注意到循环主体不触及quit变量,并将循环转换为while(true)循环。

纵然在信号处理器上为SIGINT和SIGTERM设置了quit变量;编译器无法知道这一

点。

 However,ifthequitvariableisdeclaredvolatile,thecompilerisforcedtoloaditevery

time,becauseitcanbemodifiedelsewhere.Thisisexactlywhatyouwantinthissituation.

 但是,如果quit变量被声明为volatile,编译器将被迫每次加载它,因为它可以在

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

其他地方进行修改。

这正是你在这种情况下想要的。

 122

 volatileinCactuallycameintoexistenceforthepurposeofnotcachingthevaluesof

thevariableautomatically.Itwilltellthemachinenottocachethevalueofthisvariable.

Soitwilltakethevalueofthegivenvolatilevariablefromthemainmemoryeverytimeit

encountersit.Thismechanismisusedbecauseatanytimethevaluecanbemodifiedby

theOSoranyinterrupt.Sousingvolatilewillhelpusaccessingthevalueafreshevery

time.

 实际上,在C中出现volatile是为了不自动缓存变量的值。

它将告诉机器不要缓

存这个变量的值。

因此每次它遇到主存储器时,它都会从主存储器中取出给定的可

变变量的值。

之因此使用这种机制,是因为在任何时候,操作系统或任何中断都可

以修改该值。

因此,使用volatile将帮助我们每次重新访问该值。

 53

 volatiletellsthecompilerthatyourvariablemaybechangedbyothermeans,thanthe

codethatisaccessingit.e.g.,itmaybeaI/O-mappedmemorylocation.Ifthisisnot

specifiedinsuchcases,somevariableaccessescanbeoptimised,e.g.,itscontentscanbe

heldinaregister,andthememorylocationnotreadbackinagain.

 volatile告诉编译器,与访问变量的代码相比,您的变量可以通过其他方式进行更

改。

例如,它可能是一个I/o映射的内存位置。

如果在这种情况下没有指定此选

项,则可以优化一些变量访问,例如,它的内容可以在寄存器中保存,而内存位置

不会再次读取。

 24

 SeethisarticlebyAndreiAlexandrescu,“volatile-MultithreadedProgrammer’sBest

Friend”

 请参阅安德烈·亚历山大斯库的这篇文章,“volatile—多线程程序员最好的朋友”

 Thevolatilekeywordwasdevisedtopreventcompileroptimizationsthatmight

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

rendercodeincorrectinthepresenceofcertainasynchronousevents.Forexample,ifyou

declareaprimitivevariableasvolatile,thecompilerisnotpermittedtocacheitina

register--acommonoptimizationthatwouldbedisastrousifthatvariablewereshared

amongmultiplethreads.Sothegeneralruleis,ifyouhavevariablesofprimitivetypethat

mustbesharedamongmultiplethreads,declarethosevariablesvolatile.Butyoucan

actuallydoalotmorewiththiskeyword:

youcanuseittocatchcodethatisnotthread

safe,andyoucandosoatcompiletime.Thisarticleshowshowitisdone;thesolution

involvesasimplesmartpointerthatalsomakesiteasytoserializecriticalsectionsofcode.

 volatile关键字被设计用来防止编译器优化,在某些异步事件出现时可能导致代码

不正确。

例如,如果将原始变量声明为volatile,则不允许编译器将其缓存到寄存器

中——如果在多个线程之间共享该变量,这种常见的优化将是灾难性的。

一般的规

则是,如果你有基本类型的变量必须在多个线程之间共享,那么声明这些变量是可

变的。

但是您实际上可以使用这个关键字做更多的事情:

您可以使用它来捕获不属于

线程安全的代码,并且您可以在编译时这样做。

这篇文章展示了它是如何实现的;解

决方案包括一个简单的智能指针,它还可以使代码的关键部分更容易序列化。

 ThearticleappliestobothCandC++.

 本文同时适用于C和c++。

 Alsoseethearticle“C++andthePerilsofDouble-CheckedLocking”byScottMeyers

andAndreiAlexandrescu:

 还可以参阅斯科特·迈耶斯(ScottMeyers)和安德烈·亚历山大斯库(Andrei亚历山大)

的文章《c++和双重检查锁定的危险》(c++andthedangerofdoublecheck-locked):

 Sowhendealingwithsomememorylocations(e.g.memorymappedportsormemory

referencedbyISRs[InterruptServiceRoutines]),someoptimizationsmustbe

suspended.volatileexistsforspecifyingspecialtreatmentforsuchlocations,specifically:

(1)thecontentofavolatilevariableis“unstable”(canchangebymeansunknowntothe

compiler),

(2)allwritestovolatiledataare“observable”sotheymustbeexecuted

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

religiously,and(3)alloperationsonvolatiledataareexecutedinthesequenceinwhich

theyappearinthesourcecode.Thefirsttworulesensureproperreadingandwriting.The

lastoneallowsimplementationofI/Oprotocolsthatmixinputandoutput.Thisis

informallywhatCandC++’svolatileguarantees.

 因此,在处理某些内存位置(例如,ISRs[中断服务例程]引用的内存映射端口或内

存)时,必须暂停一些优化。

波动存在指定特殊待遇等地点,具体来说:

(1)一个volatile

变量的内容是“不稳定的”(编译器可以改变通过未知),

(2)挥发性数据的写入是“看得见

的”因此他们必须执行宗教,和(3)执行所有操作波动数据序列中出现在他们的源代

码。

前两个规则确保正确的阅读和写作。

最后一个允许实现混合输入和输出的I/O

协议。

这是C和c++不稳定的保证。

 我的简单的解释是:

 Insomescenarios,basedonthelogicorcode,thecompilerwilldooptimisationof

variableswhichitthinksdonotchange.Thevolatilekeywordpreventsavariablebeing

optimised.

 在某些情况下,基于逻辑或代码,编译器会对它认为不会改变的变量进行优化。

volatile关键字防止优化变量。

 Forexample:

 例如:

 boolusb_interface_flag=0;while(usb_interface_flag==0)//executelogicforthe

scenariowheretheUSBisn’tconnectedFromtheabovecode,thecompilermaythink

usb_interface_flagisdefinedas0,andthatinthewhileloopitwillbezeroforever.After

optimisation,thecompilerwilltreatitaswhile(true)allthetime,resultinginaninfinite

loop.

 从上面的代码中,编译器可能认为usb_interface_flag定义为0,而在while循环

中,它将永远为0。

在优化之后,编译器会一直处理它(true),导致无限循环。

 Toavoidthesekindsofscenarios,wedeclaretheflagasvolatile,wearetellingto

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

compilerthatthisvaluemaybechangedbyanexternalinterfaceorothermoduleof

program,i.e.,pleasedon’toptimiseit.That’stheusecaseforvolatile.

 为了避免这种情况,我们将标志声明为volatile,我们告诉编译器这个值可能会被

外部接口或程序的其他模块所改变,例如。

,请不要优化。

这就是volatile的用例。

 16

 Amarginaluseforvolatileisthefollowing.Sayyouwanttocomputethenumerical

derivativeofafunctionf:

 挥发物的边际用途如下。

如果你想计算函数f的数值导数:

 doubleder_f(doublex)staticconstdoubleh=1e-3;return(f(x+h)-f(x))/h;The

problemisthatx+h-xisgenerallynotequaltohduetoroundofferrors.Thinkaboutit:

whenyousubstractveryclosenumbers,youlosealotofsignificantdigitswhichcanruin

thecomputationofthederivative(think1.00001-1).Apossibleworkaroundcouldbe

 问题是x+h-x一般不等于h,这是由于舍入误差造成的。

考虑一下:

当你减去非常

接近的数字时,你会丢失大量的有效数字,这会破坏导数的计算(想想1.00001-1)。

 doubleder_f2(doublex)staticconstdoubleh=1e-3;doublehh=x+h-x;return(f(x

+hh)-f(x))/hh;butdependingonyourplatformandcompilerswitches,thesecondline

ofthatfunctionmaybewipedoutbyaaggressivelyoptimizingcompiler.Soyouwrite

instead

 但是根据您的平台和编译器的切换,该函数的第二行可能会被一个积极的优化编

译器删除。

因此你写

 volatiledoublehh=x+h;hh-=x;toforcethecompilertoreadthememorylocation

containinghh,forfeitinganeventualoptimizationopportunity.

 强制编译器读取包含hh的内存位置,从而丧失最终的优化机会。

 10

 Therearetwouses.Thesearespeciallyusedmoreofteninembeddeddevelopment.

 有两个用途。

这些在嵌入式开发中特别使用。

本文由我司收集整编,推荐下载,如有疑问,请与我司联系

 Compilerwillnotoptimisethefunctionsthatusesvariablesthataredefinedwith

volatilekeyword

 编译器不会优化使用volatile关键字定义的变量的函数

 VolatileisusedtoaccessexactmemorylocationsinRAM,ROM,etc...Thisisused

moreoftentocontrolmemory-mappeddevices,accessCPUregistersandlocatespecific

memorylocations.

 Volatile用于访问RAM、ROM等中的精确内存位置。

这通常用于控制内存映射设

备、访问CPU寄存器和定位特定的内存位置。

 Seeexampleswithassemblylisting.Re:

UsageofC“volatile”KeywordinEmbedded

Development

 参见组装清单示例。

Re:

在嵌入式开发中使用C“volatile”关键字

 9

 I’llmentionanotherscenariowherevolatilesareimportant.

 我会提到另一种情况,挥发性很重要。

 Supposeyoumemory-mapafileforfasterI/Oandthatfilecanchangebehindthe

scenes(e.g.thefileisnotonyourlocalharddrive,butisinsteadservedoverthenetwork

byanothercomputer).

 假设您为更快的I/O内存映射一个文件,该文件可以在幕后更改(例如,该文件不

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1