C语言关键字volatilevolatile语法声明

许多程序员没有正确理解 C 关键字 volatile 也就不足为奇了。由于大多数 C 语言书籍通常只有一两句话,本文将向您展示如何正确使用它。在 C/C++ 嵌入式代码中,您是否经历过以下情况: 代码执行良好 – 直到您打开编译器优化 任务 如果您的答案是“是”,那么您可能没有使用 C 语言关键字 volatile。你并不孤单,许多程序员没有正确使用 volatile。不幸的是,大多数 C 语言书籍只是轻视 volatile。volatile 是声明变量时使用的限定符。它告诉编译器变量值随时可能发生变化,而变化不是由代码引起的。给编译器这个提示很重要。在我们开始之前,让’ s 看一下 volatile 的语法。C 语言关键字 volatile 语法将变量声明为 volatile,可以在数据类型之前或之后添加关键字 volatile。以下语句将 foo 声明为易失整数。将指针指向的变量声明为 volatile 是很常见的,尤其是 I/O 寄存器的地址映射。下面的语句将 pReg 声明为一个指向 8 位无符号指针的指针,该指针指向的内容是 volatile 的。

指向非易失性变量的易失性指针很少见(我只使用过一次),但无论如何我都会给出相应的语法。顺便说一下,为什么要在数据类型前使用volatile关键字,请自行百度搜索。最后,如果在 struct 或 union 之前使用 volatile 关键字,则意味着 struct 或 union 的所有内容都是 volatile。如果这不是您的意图,您可以在结构或联合成员上使用 volatile 关键字。正确使用C语言关键字volatile 只要变量可能被意外修改,都需要将变量声明为volatile。在实际应用中,只能修改三种数据: 外设寄存器地址映射 修改中断服务程序中的全局变量 在多线程、多任务的应用中,全局变量是由多个任务读写的接下来,我们将分别讨论以上三种情况。外设寄存器 嵌入式系统包含真实的硬件并且通常具有复杂的外设。这些外设寄存器的值可能会被异步修改。举个简单的例子,我们想将一个 8 位状态寄存器的地址映射到 0x1234。循环通过程序查看状态寄存器的值是否变为非零。C语言操作寄存器的方法可以参考这篇文章:C语言操作寄存器的常用方法。这是最容易想到的方法,但却是错误的方法:当您打开编译器优化时,程序总是失败。因为编译器会生成如下汇编代码: 程序优化的原因很简单,由于变量的值已经读入累加器,不需要重复,编译器认为该值不会改变。这样,在第三行,程序进入了一个无限循环。为了告诉编译器我们真正想要的是什么,我们需要修改函数的声明:

编译器生成的汇编代码:

像这样,我们得到了正确的动作。中断服务程序在中断服务程序中,经常会在主程序中修改一些全局变量值作为判断条件。例如,在一个串口中断服务程序中,有可能检测是否收到了一个ETX(如果是消息结束标识符)字符。如果收到 ETX,ISR 会设置一个全局标志。错误的方法:

关闭编译器优化,程序可以正常执行。然而,任何体面的优化都会“破坏”这个程序。问题是编译器不知道 etx_rcvd 可能在 ISR 中被修改。编译器只知道表达式 !ext_rcvd 始终为真,并且您无法退出循环。结果,循环后面的代码可能会被编译器优化掉。运气好的话没有编译器能运行c吗,你的编译器可能会发出警告;不幸的是,(或者如果您不认真对待编译器警告),您的程序将无法正确执行。当然,您可以责怪编译器执行“糟糕的优化”。解决方案是将变量 etx_rcvd 声明为 volatile 并且所有问题(当然,也许其中一些问题)都消失了。多线程用于实时系统。虽然有队列和管道等同步机制没有编译器能运行c吗,但使用全局变量在两个任务之间共享信息仍然很常见。即使您在程序中添加了抢占式调度程序,您的编译器仍然无法知道上下文切换是什么或何时发生上下文切换。所以从概念上讲,多任务修改全局变量的做法与在中断服务程序中修改全局变量是一样的。因此,所有此类全局变量都应声明为 volatile。例如下面的程序:多任务修改全局变量的做法与在中断服务程序中修改全局变量相同。因此,所有此类全局变量都应声明为 volatile。例如下面的程序:多任务修改全局变量的做法与在中断服务程序中修改全局变量相同。因此,所有此类全局变量都应声明为 volatile。例如下面的程序:

打开编译器优化时,此程序可能会失败。解决方法是将 cntr 声明为 volatile。总结 一些编译器允许你将所有变量隐式声明为 volatile。抵制停止思考的诱惑,当然会导致代码效率低下。此外,不要责怪优化器或将其关闭。现代优化器已经足够好了,以至于我不记得上次遇到优化错误是什么时候了。相反,我经常看到程序员错误地使用 volatile。如果您被要求修复一个非常奇怪的代码,请在您的程序中查找 volatile 关键字;如果你没有找到任何东西,上面讨论的例子可以给你一些解决问题的想法。结尾

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论