本帖最后由 擦鞋匠 于 2017-7-4 16:56 编辑
额,网上也看了很多介绍如何使用volatile关键字的文章,但还是感觉有些似懂非懂,不知该如何下手("最熟悉的陌生人...")~~~
问题1: 什么情况下应该使用volatile关键字?
个人理解:
volatile关键字专门是针对硬件寄存器而设定的,如下两个例子:
1>多次去读取单片机的某个标志位(这个标志位可能会被读取后由硬件自动清除),
2>多次去读取gpio的toggle寄存器(该寄存器读取后可能会被取反).
在这两种情况下,当然需要防止编译器对变量的优化,但是如果是一个纯粹的内存变量(非寄存器),我想不出,为什么一定要使用volatile关键字?恳请大神指导~~~
例如,如下是freertos中的源码,为何需要使用volatile关键字?
搜狗截图20170704165421.png (65.32 KB, 下载次数: 0)
下载附件
2017-7-4 16:56 上传
问题2: 如下两种方式在哪种使用volatile关键字方式更加合适?还是说根本就没有区别???恳请大神指教~~~
方式1: 在定义数据类型时使用volatile关键字修饰.
方式2: 在定义函数时对形参变量使用volatile关键字进行修饰.
- //方式1:
- volatile uint32_t SysVal;
- //方式2:假设SysVal只通过该形参变量传递值
- //当然,全局变量并非一定要使用形参进行传递,这里纯粹是为了讨论volatile放在哪里最合适
- void func(volatile uint32_t val)
- {
- //...
- }
复制代码
开了优化 while(i--)延时会出现什么异常呢?能详细解释一下吗,谢谢了
typedef struct {
volatile BOOLEAN wait;
Ret ret;
} Api_confirm_t;
这样定义应该可以吧
今天突然又在考虑何时应该使用volatile关键字了。于是翻看了当时ibichao大神的精彩回复。
以下是我的个人总结,如果有理解不到位,甚至错误的地方,还麻烦大神悉心指出,感谢!
* 硬件寄存器 --- 由于硬件寄存器已经超出编译器可以掌控的范围,我把它归为一个特殊的进程(一个不受编译器和程序控制的进程)。
* 中断服务程序 --- 中断服务本身就是一个进程(相对于线程,这里使用进程应该更加准确一点)。
* 多线程 --- 也是一个进程。
编译器在编译代码的时候,在某一时刻,它的眼光只能局限于一个进程(这个也能理解,毕竟这些资源的使用是在运行期间而非编译期间,编译器也无法预知)。
因此,我得出结论:在指定的某个进程范围内,如果仅仅对资源使用”读取“操作,并且在其它进程进行”写入“操作,编译器就很有可能”下黑手“。此时就需要考虑使用volatile关键字。
一周热门 更多>