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

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

3天内不再提示

C语言深入理解系列之专一王子:volatile

Q4MP_gh_c472c21 来源:未知 作者:胡薇 2018-06-11 11:13 次阅读

每个变量和其名字一样善变,有时候它善变是发自内心的,有时候是外部因素决定的,只有volatile变量才会表里如一,因此获得了专一王子的美誉。

volatile字面意思是易挥发、易变化的意思,它修饰的变量表示该变量的值很容易由于外部的因素而发生改变,强烈要求编译器要老老实实的在每次对变量进行访问时去内存里读取。

举个生活中的栗子:

你明天 有一个朋友要过生日,今天把要送的礼物打包好了,一般情况下,我们明天起来不需要再次打开验证一下里面的礼物是否存在,因为我们知道,只要礼物的外包装没有动过,里面的东西应该也没有动过。其实编译器和人一样聪明,为了提高效率也会玩省事,做优化。

如下面的例子:

编译器扫描了代码发现上面,第一行代码将10赋给了整型变量a,之后a变量的值没有再发生变化,在后面的第二行中,将a变量的值取出来赋给b,在第三行代码里面将a变量的值赋给了c的时候,因为CPU访问内存速度慢,编译器为了提高效率,玩“省事”,直接将10赋给了c。

单从上面的代码我们来看是没有问题的,就如同从外包装看生日礼物完好一样。但是,如果上述代码运行在多线程中,在一个线程上下文中没有改变它的值,但是我们却不能保证变量的值没有被其他线程所改变,就好比是,生日礼物放在其他人那里保管,我们不敢100%的确定它里面的东西完好。当然这种数据不一致的机制不仅仅出现在多线程中,同样在设备的状态寄存器里也会存在。例如,网卡里的某状态寄存器里的值是否为1表示是否有网络数据到达,在当前时刻其值为1,不能代表下一时刻它的值还是1,它的值有外界决定,编译器肯定不能在这种情况下玩“省事”,为了防止在类似的情况下编译器玩省事,可以将这些变量声明为volatile,这样不管它的值有没有变化,每次对其值进行访问的时候,都会从内存里,寄存器了读取,保证数据的一致、做到表里如一。

总结:

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:(1). 并行设备的硬件寄存器(如:状态寄存器)(2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)(3). 多线程应用中被几个任务共享的变量

(1). 一个参数既可以是const还可以是volatile吗?解释为什么。答:是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。(2). 一个指针可以是volatile 吗?解释为什么。答:是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。(3). 下面的函数有什么错误:

这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

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

    关注

    180

    文章

    7528

    浏览量

    128311
  • volatile
    +关注

    关注

    0

    文章

    44

    浏览量

    12953

原文标题:专一的王子,C语言volatile关键字解析

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    深入理解Android

    深入理解Android
    发表于 08-20 15:30

    深入理解和实现RTOS_连载

    和trcohili的帖子。深入理解和实现RTOS_连载1_RTOS的前生今世今天发布的是第篇,"RTOS的前生今世"。通过软件系统结构的比对简要的介绍rtos为何而生。如果读者对RTOS
    发表于 05-29 11:20

    深入理解和实现RTOS_连载

    和trcohili的帖子。trochili rtos完全是作者兴趣所在,且行且坚持,比没有duo。深入理解和实现RTOS_连载1_RTOS的前生今世今天发布的是第篇,"RTOS的前生今世"
    发表于 05-30 01:02

    深入理解C语言比较有用的几个资料

    这里有三个对深入理解C语言的资料,觉得不错,分享
    发表于 08-07 21:37

    51单片机C语言讲义(谭浩强)以及深入理解C指针

    本帖最后由 发烧友麒麟 于 2014-10-6 09:19 编辑 C语言讲义(谭浩强)及深入理解C指针,自己在用的资料,觉得写得挺好
    发表于 10-02 17:05

    专一王子,C语言volatile关键字解析

    每个变量和其名字样善变,有时候它善变是发自内心的,有时候是外部因素决定的,只有volatile变量才会表里如,因此获得了专一王子的美誉。
    发表于 06-11 08:26

    如何深入理解ES6函数

    深入理解ES6函数
    发表于 05-22 07:40

    深入理解STM32

    时钟系统是处理器的核心,所以在学习STM32所有外设之前,认真学习时钟系统是必要的,有助于深入理解STM32。下面是从网上找的个STM32时钟框图,比《STM32中文参考手册》里面的是中途看起来清晰些:重要的时钟:PLLCL
    发表于 08-12 07:46

    深入理解SQLite3sqlite3_exec及回调函数sqlite3

    深入理解SQLite3sqlite3_exec及回调函数sqlite3:深入理解sqlite3_stmt 机制sqlite3: sqlite3_step 函数sqlite3
    发表于 11-04 07:11

    对栈的深入理解

    为什么要深入理解栈?做C语言开发如果栈设置不合理或者使用不对,栈就会溢出,溢出就会遇到无法预测乱飞现象。所以对栈的深入理解是非常重要的。注:动画如果看不清楚可以电脑看更清晰啥是栈先来看
    发表于 02-15 07:01

    为什么要深入理解

    [导读] 从这篇文章开始,将会不定期更新关于嵌入式C语言编程相关的个人认为比较重要的知识点,或者踩过的坑。为什么要深入理解栈?做C语言开发如
    发表于 02-15 06:09

    深入理解Android之资源文件

    深入理解Android之资源文件
    发表于 01-22 21:11 22次下载

    深入理解Android》文前

    深入理解Android》文前
    发表于 03-19 11:23 0次下载

    深入理解Android:卷I》

    深入理解Android:卷I》
    发表于 03-19 11:23 0次下载

    STM32编程:是时候深入理解栈了<一>

    为什么要深入理解栈?做C语言开发如果栈设置不合理或者使用不对,栈就会溢出,溢出就会遇到无法预测乱飞现象。所以对栈的深入理解是非常...
    发表于 01-26 17:55 2次下载
    STM32编程:是时候<b class='flag-5'>深入理解</b>栈了<一>