• 关于Volatile的解读


    一直想看一看 volatile 的用法,之前就看过这种静态量是不会被编译器无意破坏的,但是一直没有搞彻底明白。

    今天查看了大量前辈们的总结,自己又有了新的心得,写下此随笔来分享自己的心得。

    最开始接触 volatile 是在STM32程序的 __IO 中,其中#define __IO  volatile

    (下面一段来自维基百科对Volatile的解读)

    volatile关键字用来阻止(伪)编译器认为的无法“被代码本身”改变的代码(变量/对象)进行优化。如在C语言中,

    volatile关键字可以用来提醒编译器它后面所定义的变量随时有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

    (上面一段来自维基百科对Volatile的解读)

    在C语言中,编译器会根据你得代码进行优化,而 volatile 最直接的就是,告诉编译器不要优化这一个变量的运算过程。

    (下面图片来自维基百科)

    (上面图片来自维基百科)

    在汇编下,可以很明确的看出使用Volatile后编译器不会让你的代码丢失。

    先说下使用volatile的好处:

    1.volatile允许除了程序以外的事件来改变它的内容,比如硬件直接改变。

    2.每次读取volatile的内容都是直接访问该地址的内容,不是通过cache( 高速缓冲存储器)来访问。

    稍稍解释一下:1.我们告诉编译器,volatile类型的变量的确可能被外部条件改变,比如硬件设备。

    2.正常情况下,如果我们不加volatile的话,在共享地址区的变量程序并不知道它什么时候被改变,你读取的只可能是cache里面的变量,而这个变量可能是过时的变量。

    3.(补充)私有地址里面的内容,程序可以直接访问

    回到我们的截图内容

    #define __IO  volatile

    #define uint32_t  uisigned long

    如果是(volatile unsigned long *) (0x1FFF7A10),再分解看(volatile unsigned long *)是一个为随硬件需要定义的一种地址,前面加上*指针,即直接指向改地址,整个定义#define CPU_Sn0,调用的时候直接向地址寄存器写内容就好了。这是内存机制的方便性,volatile是嵌入式系统开发发一个重要特点。

    再将其展开来分析:(volatile unsigned long *) (0x1FFF7A10)的意思就是将0x1FFF7A10强制转化成volatile unsigned long的指针,然后赋给CPU_Sn0就是表达CPU_Sn0为指向地址的内容了。这里是通过内存寻址访问寄存器,可以进行读/写操作。

    再通过这个volatile去分析,关键字volatile 确保本条指令不会因C 编译器的优化而被省略,且要求每次直接读值。例如用while((unsigned char *)0x1FFF7A10)时,有时系统可能不真正去读0x1FFF7A10的值,而是用第一次读出的值,如果这样,那这个循环可能是个死循环。用了volatile 则要求每次都去读0x1FFF7A10的实际值。那么它就是一个固定的指针,而char *p;是一个指针变量。

    再在前面加一个 “*” :则变成了变量,只不过这是一个地址固定的指针变量。

  • 相关阅读:
    单元测试、集成测试、系统测试
    函数
    python中的math函数
    字符串和数据类型转换
    range()函数
    input()函数
    Linux如何通过命令查看日志文件的某几行(中间极几行或最后几行)
    【转】接口测试面试题
    【转】用Fiddler做抓包分析详解
    为什么要使用fiddler抓包?抓包用来干什么?
  • 原文地址:https://www.cnblogs.com/qiaoyonggang/p/11256340.html
Copyright © 2020-2023  润新知