许多低级程序使用volatile关键字来进行内存映射的类型等,但是我对其在后台真正执行操作感到困惑。换句话说,当编译器没有“优化”内存地址时,这意味着什么?
许多低级程序使用volatile关键字来进行内存映射的类型等,但是我对其在后台真正执行操作感到困惑。换句话说,当编译器没有“优化”内存地址时,这意味着什么?
Answers:
volatile
意味着其他一些处理器或I / O设备或某些东西可以将变量从您的下方更改。
使用普通变量,程序的步骤是唯一可以更改它的步骤。因此,举例来说,如果您5
从变量中读取但未更改它,则该变量仍包含5
。由于您可以依靠它,因此您的程序不必在下次要使用它时花时间再次读取该变量。C ++编译器很聪明,可以生成只记住的代码5
。
但是您可以将其读取为5
,然后系统可能会将数据从磁盘加载到该内存中,并将其更改为500
。如果您希望程序读取新的值500
,则需要编译器不要对使用先前读取的内容太聪明5
。您需要告诉它每次都重新加载该值。就是volatile
那样
比方
说5岁的孩子,假设您在一张桌子上放了一张大纸。在本文的一个角落,您写下正在进行的游戏的当前得分3 to 4
。然后,您转到桌子的对面,开始写有关游戏的故事。您正在观看游戏的朋友会在游戏进行时更新该角点的分数。她擦除3 to 4
并写作3 to 5
。
当您将游戏得分添加到故事中时,您可以:
3 to 4
,快乐地假设它没有变化(或介意它没有变化),或3 to 5
现在),然后往回走。这就是volatile
变量的作用方式。volatile
意味着两件事:
变量的值可能会更改,而您的任何代码都不会更改它。因此,无论何时编译器读取该变量的值,都可能不会假定该变量与上次读取的变量相同,或假定它与存储的最后一个值相同,但必须再次读取。
从易失性变量存储值的行为是“副作用”,可以从外部观察到,因此不允许编译器删除存储值的行为。例如,如果两个值连续存储,那么编译器实际上必须将该值存储两次。
举个例子:
i = 2;
i = i;
编译器必须存储第二个数字,读取变量i,并将其读取的变量存储到i中。
还有另一种情况:如果某个函数使用setjmp
然后longjmp
被调用,则该函数的所有易失性局部变量都将保证存储了最后一个值-非易失性局部变量不是这种情况。
i
和value pi = &i
,则x = *pi
从中进行读取i
,但不能保证该读取具有易变的语义。
i
声明为,volatile int i
那么pi
必须声明为volatile int *pi
,在这种情况下*pi
是易失性访问,不是吗?
抽象说明
C和C ++都具有抽象机的概念。当代码使用某个变量的值时,抽象机表示实现必须访问该变量的值。表单的代码statement_A; statement_B; statement_C;
必须严格按照指定的顺序执行。这三个语句共有的表达式每次出现时都必须重新计算。
对于抽象机,给定语句序列statement_A; statement_B; statement_C;
,实现必须首先statement_A
完整地执行,然后再statement_B
最后执行 statement_C
。该实现不记得您已将age
值分配为5。每个引用的语句都age
必须访问该变量的值。
volatile
如果实现根据抽象机规范严格执行C或C ++代码,则不需要关键字。C和C ++抽象机没有寄存器的概念,没有公共子表达式的概念,并且执行顺序严格。
两种语言也都有“如果”规则。只要该实现的行为就像已按照抽象机规范执行了所有事情,那么该实现就符合该标准。编译器可以假定非易失性变量在分配之间不会更改值。只要不违反as-if
规则,就statement_A; statement_B; statement_C;
可以通过执行的一部分statement_C
,然后的一部分statement_A
,然后的全部statement_B
,然后的其余部分statement_A
,最后执行的其余部分来实现该序列statement_C
。
这些假设规则不适用于volatile
变量。关于volatile
变量和函数,实现必须完全按照您告诉它的操作去做,并且必须按照您告诉它做事的顺序去做。
抽象机器规范有一个缺点:很慢。与其他语言相比,C和C ++的一个积极方面是它们非常快。如果代码是针对这些抽象机执行的,则情况并非如此。在AS-如果规则是什么让C和C ++是如此之快。
ELI5答案
编译器未“优化”内存地址是什么意思?
“优化”内存地址是一个高级概念,这不在五岁儿童的能力范围之内。顺从的五岁孩子会完全按照您告诉他们的去做,不会多也不会少。使用volatile
,您将告诉实现的实现就像是五个实现:没有思考,没有花哨的优化。取而代之的是,实现必须完全执行代码告诉它的操作。
答案似乎很一致,但缺少要点。您告诉编译器您要分配空间,对于每次访问,读或写,都希望它执行该访问。由于某些原因,我们不希望它优化这些访问或该变量。
是的,原因之一是因为其他人可能会改变我们的价值。另一个原因是我们可能会为其他人更改该价值。有人是为我们更改它的人还是我们为之更改它的人可能是硬件/逻辑或软件。它通常用于定义对裸机嵌入式程序中的控制和状态寄存器的访问,以及对硬件的写入或读取。以及与软件对话的软件在其他答案中有所说明。
如果您试图定时一段代码,并且您不使用volatile,那么您还将看到volatile用于控制访问的时间和顺序,如果您不使用volatile,则仅需考虑有问题的变量(开始时间,结束时间和差值)。计算接近结束时,编译器可以随意移动任意一个时间测量值(而不是放置它们的位置),这并不是说它不能随时间变化,但是经验表明它不太可能。
有时,您会看到它过去只是用来消耗时间,一个基本的led指示灯,即裸机的世界,可能会使用volatile变量来计数,该变量计数很大,只是为了消耗时间让人眼看到led改变状态。然后,使用更高级的示例使用计时器或其他事件来消耗时间。
volatile
变量中读取年龄并显示5,那么明年再读一次,您