读文章之前 可以先看一下《程序员的自我修养 》第28页 过度优化。

volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有 volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序:
short flag;
void test()
{
do1();
while(flag==0);
do2();
} 这段程序等待内存变量flag的值变为1(怀疑此处是0,有点疑问,)之后才运行do2()。变量flag的值由别的程序更改,这个程序可能是某个硬件中断服务程序。例如:如果某个按钮按下的话,就会对DSP产生中断,在按键中断程序中修改flag为1,这样上面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的值先读入某个寄存器,然后等待那个寄存器变为1。如果不幸进行了这样的优化,那么while循环就变成了死循环,因为寄存器的内容不可能被中断服务程序修改。为了让程序每次都读取真正flag变量的值,就需要定义为如下形式:
volatile short flag;
需要注意的是,没有volatile也可能能正常运行,但是可能修改了编译器的优化级别之后就又不能正常运行了。因此经常会出现debug版本正常,但是release版本却不能正常的问题。所以为了安全起见,只要是等待别的程序修改某个变量的话,就加上volatile关键字。

volatile的本意是“易变的”

由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:

static int i=0;

int main(void)
{
   ...
   while (1)
   {
      if (i) do_something();
   }
}

/* Interrupt service routine. */
void ISR_2(void)
{
   i=1;
}

程序的本意是希望ISR_2中断产生时,在main当中调用do_something函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致do_something永远也不会被调用。如果将将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

一般说来,volatile用在如下的几个地方:

1、中断服务程序中修改的供其它程序检测的变量需要加volatile;

2、多任务环境下各任务间共享的标志应该加volatile;

3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

volatile 的含义
  volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化,volatile的字面含义是易变的,它有下面的作用:

1 不会在两个操作之间把volatile变量缓存在寄存器中。在多任务、中断、甚至setjmp环境下,变量可能被其他的程序改变,编译器自己无法知道,volatile就是告诉编译器这种情况。

2 不做常量合并、常量传播等优化,所以像下面的代码:
volatile int i = 1;
if (i > 0) ...

if的条件不会当作无条件真。

3 对volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没用到,编译器常常可以省略那个赋值操作,然而对Memory Mapped IO的处理是不能这样优化的。

前面有人说volatile可以保证对内存操作的原子性,这种说法不大准确,其一,x86需要LOCK前缀才能在SMP下保证原子性,其二,RISC根本不能对内存直接运算,要保证原子性得用别的方法,如atomic_inc。

对于jiffies,它已经声明为volatile变量,我认为直接用jiffies++就可以了,没必要用那种复杂的形式,因为那样也不能保证原子性。

你可能不知道在Pentium及后续CPU中,下面两组指令

inc jiffies
;;
mov jiffies, %eax
inc %eax
mov %eax, jiffies

作用相同,但一条指令反而不如三条指令快。

c语言中volatile关键字的作用相关推荐

  1. C语言中static关键字的作用

    在C语言中static的作用如下 第一.在修饰变量的时候,static修饰的静态局部变量只执行一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放.  第二.static修饰全局变量的时候, ...

  2. c语言中volatile关键字

    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改. 用volatile关键字声明的变量i每一次被访问时,执行部件都会从i相应的内存单元中取出i的值. 没有用 ...

  3. C语言中static关键字的作用详解,全网最透彻

    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有 ...

  4. char* 赋值 const char* 释放_C/C++编程笔记:C语言中 const 关键字的作用及解析,值得收藏!...

    有时候我们希望定义这样一种变量,它的值不能被改变,在整个作用域中都保持固定.例如,用一个变量来表示班级的最大人数,或者表示缓冲区的大小. 为了满足这一要求,可以使用const关键字对变量加以限定: c ...

  5. c语言volatile含义,c语言中volatile关键字是什么含义怎么办呢?

    满意答案 yyvalentine 2016.11.26 采纳率:56%    等级:11 已帮助:4891人 C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立 ...

  6. 【嵌入式】C语言中volatile关键字

    00. 目录 文章目录 00. 目录 01. volatile概述 02. volatile应用场景 03. volatile应用示例 04. 嵌入式系统中应用 05. volatile官方说明 vo ...

  7. C语言中volatile关键字与汇编__volatile__

    在gcc中,可以使用 __asm__ 进行汇编语言的内嵌. __volatile__ 表明编译器不要优化代码,后面的指令保持原样. C语言关键字volatile表明某个变量的值在外部可能被改变,因此对 ...

  8. C语言中voliate关键字的作用

    一个变量用voliate关键字修饰,是要告诉编译器,这个变量的值随时可能发生变化,所以编译器每次都必须从变量对应的内存地址中获取该变量的值. voliate的常用方式: 当一个变量表示某寄存器的值时, ...

  9. C语言中const关键字的作用

    1.可以定义const常量,具有不可变性.例如:const int Max=100; Max++会产生错误; 2.便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患.例如: void f( ...

最新文章

  1. Windows 2008 远程登陆时提示要登录到此远程计算机,您必须被授予允许通过终端登录登录的权限...
  2. apollo在liunx环境实战(三)
  3. 成功解决AttributeError: module 'numpy' has no attribute 'equal'
  4. 【6 插值方法】实例实战篇
  5. 无法加入nacos服务列表_Nacos 1.1.1 发布,支持灰度配置和地址服务器模式
  6. RethinkDB已经将其数据库移植到Windows
  7. 字典java程序_编程字典-Java xxxValue() 方法
  8. 微拍堂推出“正义联盟计划” 助力文玩行业高质量发展
  9. 下载代码的两种方式ssh 和 https
  10. 职称专业技术工作小结 计算机,申报计算机专业中级职称任职来专业技术工作总结(范文).doc...
  11. 鸿蒙系统主页面斜纹,《中国美术欣赏》[精选].doc
  12. 随机的力量(1) - The power of random two choices
  13. ue4学习日记4(植被,光照,光束遮挡,天空球)
  14. 【Java从零到架构师第二季】【07】JDBC FOR MySQL
  15. argc与argv参数的含义
  16. limbo运行veket linux,veket linux系统下载-veket操作系统v20 最新版 - 极光下载站
  17. Fabric CA/数字证书管理
  18. 计算机曲谱卡农,卡农曲谱.doc
  19. 画论51 沈灏《画尘》
  20. Java8时间校正器

热门文章

  1. Scala:Functions and Closures
  2. android帧动画实现方法之一
  3. 使用 雨林木风 Ghost XP SP3 装机版 YN9.9 安装 Win7 (SP1)
  4. 爱不释手(Typingfaster)1.78beta,重大升级,欢迎试用,期待反馈。
  5. mysql数据导入python_利用python将mysql中的数据导入excel
  6. php取后三字符串,php字符串截取问题
  7. 在win7怎么使用linux指令,Win7系统的Powershell命令怎么使用
  8. android 汉字编码,Android解压中文乱码
  9. java 头尾 队列_记一次腾讯面试,我挂在了最熟悉不过的队列上
  10. pch在c语言中占内存字节数,2018年9月计算机二级C语言考试章节习题及答案(6).docx...