C语言学习及应用笔记之四:C语言volatile关键字及其使用
在C语言中,还有一个并不经常使用但却非常有用的关键字volatile。那么使用volatile关键字究竟能干什么呢?接下来我将就此问题进行讨论。
一个使用volatile关键字定义变量,其实就是告诉编译系统这变量可能会被意想不到地改变。那么编译时,编译器就不会自作主张的去假设这个变量的值,而进行代码的优化了。确切的说就是,编译器在编译代码时,优化器每次遇到这个变量,都会到内存中重新读取,而不会使用保存在寄存器里的备份来对代码进行优化。
我们已经了解了volatile关键字的基本作用。那么,在什么情况下使用volatile关键字呢?一般说来,在如下的几种情况通常会使用volatile关键字:
- 在中断服务程序中修改的,供其它程序检测的变量,通常需要定义为volatile;
- 在多任务环境下,各任务间共享的标志,通常也需要定义为volatile;
- 存储器映射的硬件寄存器通常也需要定义为volatile,因为每次对它的读写都可能有不同意义;
(1)使用中断改变对象值的情况
我们在中断服务程序中操作了某个对象,比如谁改变了一个变量的值。而在其它程序中我们希望通过这个变量值得改变去进行一些操作。在这个时候,我们使用或者不使用volatile关键字,可能得到截然不同的结果。
如果我们将变量定义为:static int var=0; ,然后再中断服务成勋中将其修改为:var=1,但是在另一函数中使用它但不会修改它,那么编译器会认为它没有变化,从而直接使用寄存器中的副本。
如果我们将变量定义为:volatile int var=0;,那么结果就完全不同了,每次在函数中使用var变量时,都会重新读取,而不会使用寄存器中的副本。
(2)多任务共享标志的情况
多任务共享时,其实也是一样的,在一个任务中修改了一个对象后,在另一个对象中应用它,但编译器并没发现在该任务中对它有修改。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。从而并不能响应在另一任务下的变化。
在这种情况下,一般我们都需要使用volatile关键字来定义任务间共享的标识。
(3)硬件寄存器内存映射的情况
内存映射的情况是非常多的,比如我们将外设的寄存器映射到内存的某一段区域;再比如我们同过DMA方式将数据直接写到内存中的某一段区域。
由于我们外部的数据都是直接进入了内存区域,而程序知识引用它的值。编译器优化时可能就直接采用寄存器中的副本了。佷显然这不是我们需要的结果,这时将这段内存对应的变量声明为volatile,则可以保证我们的需求。
综上所述,我们说明了volatile关键字的常规用法。当然,我们也可以发现volatile关键字是会降低编译器优化力度的,但它却可以保证程序的正确性,所以在适合的地方使用volatile关键字是必要的。不过能不能用的好,还要看编程者的基本功。
欢迎关注:

C语言学习及应用笔记之四:C语言volatile关键字及其使用的更多相关文章
- C语言学习及应用笔记之一:C运算符优先级及使用问题
C语言中的运算符绝对是C语言学习和使用的一个难点,因为在2011版的标准中,C语言的运算符的数量超过40个,甚至比关键字的数量还要多.这些运算符有单目运算符.双目运算符以及三目运算符,又涉及到左结合和 ...
- GO语言学习(十六)Go 语言结构体
Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...
- C语言学习书籍推荐《C程序设计语言(第2版•新版)》下载
克尼汉 (作者), 等 (作者, 译者), 徐宝文 (译者) 下载地址:点我 <C程序设计语言(第2版•新版)>是由C语言的设计者Brian W.Kernighan和Dennis M.Ri ...
- C语言学习及应用笔记之七:C语言中的回调函数及使用方式
我们在使用C语言实现相对复杂的软件开发时,经常会碰到使用回调函数的问题.但是回调函数的理解和使用却不是一件简单的事,在本篇我们根据我们个人的理解和应用经验对回调函数做简要的分析. 1.什么是回调函数 ...
- C语言学习及应用笔记之五:C语言typedef关键字及其使用
在C语言中有一个typedef关键字,其用来定义用户自定义类型.当然,并不是真的创造了一种数据类型,而是给已有的或者符合型的以及复杂的数据类型取一个我们自己更容易理解的别名.总之,可以使用typede ...
- C语言学习及应用笔记之三:C语言const关键字及其使用
在C语言程序中,const关键字也是经常会用到的一个关键字,那么使用const关键字的目的是什么呢?事实上,在程序中使用const关键字的主要目的就是为了向使用者传递设计者的一些意图. 事实上,无论我 ...
- C语言学习及应用笔记之二:C语言static关键字及其使用
C语言有很多关键字,大多关键字使用起来是很明确的,但有一些关键字却要相对复杂一些.我们这里要说明的static关键字就是如此,它的功能很强大,相应的使用也就更复杂. 一般来说static关键字的常见用 ...
- C语言学习及应用笔记之六:C语言extern关键字及其使用
在C语言中,修饰符extern用在变量或者函数的声明前,用来以标识变量或者函数的定义在别的文件中,提示编译器遇到此变量或者函数时,在其它文件中寻找其定义.extern关键字的用法有几种,我们下面对其进 ...
- 从零开始学习SSH框架笔记之四 几个关键配置文件备忘(模板)
不多说,直接上代码.关于注释我尽量写详细点. 1.web.xml <?xml version="1.0" encoding="UTF-8"?> &l ...
随机推荐
- 家庭记账本小程序之增(java web基础版三)
实现新增消费账单 1.main_left.jsp中该部分,调用add.jsp 2. add.jsp,提交到Servlet的add方法 <%@ page language="java&q ...
- SQLiteOpenHelper+ContentProvider的使用
效果图: PetDbHelper package com.example.admin.pets; import android.content.Context;import android.datab ...
- 如何批量修改网页 更新网站 一键保存 windows查看和排序
批量打开需要修改的网页,一键保存:一个网站会由很多网页组成,当需要大量更新的时候,如果一个个进行打开修改,效率会很低,内容修改不多,且容易修改的时候,可以用editplus这种小编辑软件批量打开,批量 ...
- 修改Linux的编码集
使用SSH secure远程连接linux时,查看linux里的内容, 发现乱码.这是由于SSH secure客户端的编码是gbk ,而 linux的默认编码是utf-8 要解决乱码问题,必须将lin ...
- Linux磁盘空间被未知资源耗尽
在linux中,当我们使用rm在linux上删除了大文件,但是如果有进程打开了这个大文件,却没有关闭这个文件的句柄,那么linux内核还是不会释放这个文件的磁盘空间,最后造成磁盘空间占用100%, ...
- 【CF1133E】K Balanced Teams(动态规划,单调队列)
[CF1133E]K Balanced Teams(动态规划,单调队列) 题面 CF 让你把一堆数选一些出来分成不超过\(K\)组,每一组里面的最大值和最小值之差不超过\(5\),求最多有多少个人元素 ...
- layui加载层
layer.load(1, { shade: [0.5, '#000'], //0.5透明度的灰色背景 content: '注册中...', success: function (layero) { ...
- 2017-12-19python全栈9期第四天第二节之列表的增删查改之正向排序和倒向排序和反转
#!/user/bin/python# -*- coding:utf-8 -*-li = [3,5,6546,6,8,324,2,1,34,5,6,7]# li.sort() #正向# print(l ...
- 工厂方法模式-Factory Method(Java实现)
工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...
- 分享一个自搭的框架,使用Spring boot+Vue+Element UI
废弃,新的:https://www.cnblogs.com/hackyo/p/10453243.html 特点:前后端分离,可遵循restful 框架:后端使用Spring boot,整合了aop.a ...