0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

编译器通常会怎么去处理使用volatile修饰的变量呢?

lilihe92 来源:最后一个bug 2023-11-29 10:05 次阅读

正文

嵌入式软件开发过程中,如果对volatile不熟,那可以你应该是个"假嵌入式程序员",因为一个变量需不需要使用volatile考虑的场景挺多的,如果在某些场景下乱用,会影响程序运行效率,有时候忘记加甚至会使得程序发生异常,那么bug菌今天就大家好好聊聊这个C语言关键字:

1

传统定义

volatile直译为“易变的”,也就是告诉编译器这个变量随时都可能发生变化,编译器你跟我“特殊照顾一下“。

那么编译器通常会怎么去处理使用volatile修饰的变量呢?

对于C变量都是代表着对应的内存,读取使用volatile修饰的变量,会直接从其所对应的内存地址中获取最新的数据,否则,编译器会对其访问进行优化,比如直接从缓存中读取副本、或者是从寄存器中读取副本。

这样就可能会导致数据更新不一致的问题。

2

最常用的地方

从前面对volatile的功能描述,我们可以知道volatile最常用于那些与硬件外设寄存器打交道的地址,这样确保每次对寄存器的读取都是从内存中获取的最新值,比如:

2f457242-8df4-11ee-939d-92fbcf53809c.png

再比如下图所示,如果我们向地址0x812100地址连续改变其值:

2f58b3ac-8df4-11ee-939d-92fbcf53809c.png

那么编译器通常会将其直接优化为第三条操作,并不会去执行前两条操作,这样会造成写寄存器时序上的问题。

如果采用volatile去修饰,则三条命令便会依次执行,达到我们代码所示三次操作的目的。

2f62bf46-8df4-11ee-939d-92fbcf53809c.png

3

更复杂一点的,也是最重要的

其实对于volatile所解决的问题用更加专业的说法可以分为:可见性和有序性。

1、可见性

所谓可见性,通常是在多线程访问共享数据的情况,当一个线程对共享变量进行修改,而其他线程能否立即观察到这个修改的性质。

在我们目前大部分单核一级缓存的CPU无需考虑这个问题,而对于现场多核多级缓存处理器,各个现场都会维护着自己的缓存,如果仅仅只是更新到了自己的缓存中那么其他线程是无法立马感受到这个修改的,最终导致结果不一致。

2、有序性

很多时候也叫作重排序,说白了就是对执行指令进行了执行顺序上的优化,以不改变指令运行的最终结果,而改变指令的执行顺序。

编译器可以调整指令,同样处理器的多级流水线和乱序执行也同样可以改变指令执行顺序;甚至为了多级缓存的高效执行,也同样会对内存读写操作进行重排序。

然而这样的重排序,却会对多线程并发访问共享数据的过程中产生问题,从而不符合我们编程源码的预期执行顺序。

但对于volatile只能在一定程度上防止指令重排序,其只能保证单个变量访问的有序性,而不能保证整个程序的有序性,所以这一点是大家尤为要注意的。

所以讲了这么多,相信以后大家再开发中也都会遇到。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5036

    浏览量

    117762
  • C语言
    +关注

    关注

    180

    文章

    7533

    浏览量

    128813
  • 嵌入式软件
    +关注

    关注

    4

    文章

    228

    浏览量

    26386
  • volatile
    +关注

    关注

    0

    文章

    44

    浏览量

    12954

原文标题:这个变量要不要用volatile修饰呢?

文章出处:【微信号:最后一个bug,微信公众号:最后一个bug】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    volatile 释义

    取出i的值,因而编译器生成的汇编代码会重新从内存中i的地址处读取i的值存放在k中。一句话概括就是,当用volatile关键字修饰变量时,优化
    发表于 08-05 16:06

    【原创分享】单片机编程关键字之volatile

    ,那么两个线程有可能一个使用内存中的变量,一个使用寄存中的变量,这回造成程序的错误执行。那么用了volatile修饰
    发表于 06-29 11:17

    volatile关键字应用场景及示例

    volatile关键字1.应用场景2.示例1.应用场景volatile关键字分析,往往应用在三种场合1)多线程编程共享全局变量的时候,该全局变量要加上
    发表于 08-24 07:21

    volatile是什么?其用法是什么

    volatile关键字声明的变量,在每次对其值进行引用的时候都会从原始地址取值。由于该值“易变”的特性所以,针对其的任何赋值或者获取值操作都会被执行(而不会被优化)。由于这个特性,所以该关键字在嵌入式编译环境中经常用来消除
    发表于 01-24 07:12

    编译器之位域和volatile研究

    1、位域和volatile介绍  位域和volatile大家再熟悉不过了:前者用于将指定类型的整形变量按照我们的意愿像蛋糕一样切分成或大或小的若干份;后者用于告诉编译器“绝不允许对被
    发表于 11-11 18:09

    C语言中的volatile关键字

    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。
    发表于 05-27 09:32 3181次阅读

    Volatile与多线程的认识与理解

    不会因编译器的优化而省略,且要求每次直接读值。volatile变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个
    发表于 12-01 10:31 1570次阅读

    volatile变量定义的意义和该用在哪里

    volatile 影响编译器编译的结果,volatile指出 变量是随时可能发生变化的,与volatil
    发表于 03-07 15:29 3540次阅读
    <b class='flag-5'>volatile</b><b class='flag-5'>变量</b>定义的意义和该用在哪里

    C语言类型修饰Volatile的使用说明

    ,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。volatile变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设
    的头像 发表于 09-19 10:54 3297次阅读

    关于volatile关键字对编译器优化的影响

    volatile关键字对编译器优化的影响
    的头像 发表于 02-28 17:15 2646次阅读

    虚拟机:编译器对C函数的名字修饰

    虚拟机:编译器对C函数的名字修饰
    的头像 发表于 06-22 11:44 2369次阅读
    虚拟机:<b class='flag-5'>编译器</b>对C函数的名字<b class='flag-5'>修饰</b>

    如何使用C++语法中的volatile

    volatile volatile int i = 10; volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些
    的头像 发表于 09-09 09:38 1302次阅读

    C++基础语法之volatile、assert()和sizeof()

    volatile volatile int i = 10; volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些
    的头像 发表于 09-09 09:48 1128次阅读

    漫谈C变量——优化天敌“volatile

    在前面的文章《编译器玄学报告第一期》中,我们了解到:volatile实际上是告诉编译器“绝不允许对被修饰变量动手动脚(做优化)”,因为..
    发表于 01-25 18:43 0次下载
    漫谈C<b class='flag-5'>变量</b>——优化天敌“<b class='flag-5'>volatile</b>”

    一文详解volatile关键字

    volatile 是易变的、不稳定的意思。和const一样是一种类型修饰符,volatile关键字修饰变量
    的头像 发表于 02-15 11:54 764次阅读
    一文详解<b class='flag-5'>volatile</b>关键字