当前位置: 首页 > 编程日记 > 正文

c语言中volatile关键字的作用

读文章之前 可以先看一下《程序员的自我修养 》第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

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

相关文章:

Java项目:抽奖点名神器(HTML+可自定义抽选)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 用于年终抽奖或随机点名神器 //获取页面元素var student_box document.getElementById("student_box");//循环生成HTMLvar html "";for (var i 0 ; i < 22; i ) {html <div st…

Hive Metastore 连接报错

背景 项目中需要通过一些自定义的组件来操控hive的元数据&#xff0c;于是使用了remote方式来存储hive元数据&#xff0c;使用一个服务后台作为gateway&#xff0c;由它来控制hive元数据。 现象 在windows上连接hive metastore的时候&#xff0c;无端的会报NullPointerExceptio…

普通的简单对话框

2019独角兽企业重金招聘Python工程师标准>>> activity_main.xml <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:layout_width"fill_parent"and…

[POI2007]ZAP-Queries

出处&#xff1a;http://www.cnblogs.com/peng-ym/p/8660937.html &#xff08;还是 建议 去看 原文&#xff09; 题目&#xff1a;链接&#xff1a;https://www.luogu.org/problemnew/show/P3455 #include<bits/stdc.h> #define LL long long #define ULL unsigned long…

python pdb 基础调试

当手边没有IDE,面对着python调试犯愁时&#xff0c;你就可以参考下本文&#xff1b;&#xff08;pdb 命令调试&#xff09;参考&#xff1a;http://docs.python.org/library/pdb.html和 (pdb)help首先你选择运行的 pypython -m pdb myscript.py(Pdb) 会自动停在第一行&#xff…

Java项目:设计管理系统(java+SSM+JSP+MYSQL+layui+Maven)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 一、项目简述 功能包括&#xff1a; 课题管理&#xff0c;学生管理&#xff0c;内容管理&#xff0c;文件管理&#xff0c;提问管理&#xff0c;教师管理&#xff0c;进度管理等等。 二、项目运行 环境配置…

linux(以ubuntu为例)下Android利用ant自动编译、修改配置文件、批量多渠道,打包生成apk文件...

原创&#xff0c;转载请注明&#xff1a;http://www.cnblogs.com/ycxyyzw/p/4555328.html 之前写过一篇《windows下Android利用ant自动编译、修改配置文件、批量多渠道&#xff0c;打包生成apk文件》&#xff0c;关于ant打包原理&#xff0c;请先阅读此篇文章&#xff0c;再阅…

自制的一个eclipse 插件jcodesmith(代码生成器)

为什么80%的码农都做不了架构师&#xff1f;>>> 实现思路 使用模板输出&#xff0c;定制一些特定的输入【如数据库元素、普通文件】等控制模板生成&#xff1b;并把指定输入可视化&#xff0c;方便使用&#xff1b; 下载安装 插件下载&#xff1a;http://git.os…

Boring counting HDU - 3518 (后缀数组)

Boring counting \[ Time Limit: 1000 ms \quad Memory Limit: 32768 kB \] 题意 给出一个字符串&#xff0c;求出其中出现两次及以上的子串个数&#xff0c;要求子串之间不可以重合。 思路 对字符串后缀数组&#xff0c;然后枚举子串长度 \(len\)&#xff0c;若某一段连续的 \…

什么是JTAG

JTAG(Joint Test Action Group)联合测试行动小组)是一种国际标准测试协议&#xff08;IEEE 1149.1兼容&#xff09;&#xff0c;主要用于芯片内部测试。现在多数的高级器件都支持JTAG协议&#xff0c;如DSP、FPGA器件等。标准的JTAG接口是4线&#xff1a;TMS、 TCK、TDI、TDO&a…

Java项目:个人博客系统(java+SSM+Mysql+Servlet+JavaWeb)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 一、项目简述 项目内容包括&#xff1a;首页&#xff0c;登陆&#xff0c;新建文章&#xff0c;搜索&#xff0c;登陆日志&#xff0c;登录次数&#xff0c;评论统计&#xff0c;相关信息&#xff0c;文章列…

Lucene4 入门(2)–Field类及辅助类说明

2019独角兽企业重金招聘Python工程师标准>>> Lucene4 入门(2)–Field类及辅助类说明 一、Eclipse中Field类的继承关系图&#xff1a; 二、Field类 1、 类的说明 在一般情况下为Document对象创建一个Field对象会使用它的子类&#xff0c;比如&#xff1a; IntField,…

C#入门详解(4)

什么是类型 类型又名数据类型。表示数据在内存中存储时的型号。小内存容纳大尺寸数据会丢失精度&#xff0c;发生错误。 大内存容纳小尺寸的数据会导致内存浪费。 编程语言的数据类型与数据的数据类型不完全相同。 类型在C#语言中的作用 类型所包含的信息有&#xff1a; 存储此…

使用 Trace32 对 FLASH 编程

from: http://www.ibm.com/developerworks/cn/linux/l-trace32/随着软硬件复杂性的增加&#xff0c;在嵌入式系统开发中&#xff0c;调试器对项目的开发进度、质量起着越来越重要的作用。在众多的调试器中&#xff0c;Lauterbach 公司的 Trace32 凭借其强大的功能&#xff0c…

Farseer.net轻量级ORM开源框架 V1.x 入门篇:新版本说明

导航目 录&#xff1a;Farseer.net轻量级ORM开源框架 目录 上一篇&#xff1a;没有了 下一篇&#xff1a;Farseer.net轻量级ORM开源框架 V1.x 入门篇&#xff1a;数据库配置 前言V1.x版本终于到来了。本次版本的开发从3月份开始&#xff0c;花了一个月的时间完成了概念版本设…

Java项目:健身管理系统(Java+ssm+springboot)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 主要技术&#xff1a;springmvc、 springboot 、mybatis、mysql 、jQuery、layui、css、jsp shiro权限控制 主要功能截图如下&#xff1a; 用户登录、首页主要功能有&#xff1a;会员信息管理、会员到期续费…

计算几何算法概览

为什么80%的码农都做不了架构师&#xff1f;>>> 计算几何算法概览一、引言 计算机的出现使得很多原本十分繁琐的工作得以大幅度简化&#xff0c;但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案&#xff0c;比如几何问题。作为计算…

诚意租房网blog2

&#xff08;一&#xff09;数据库设计部分&#xff1a; 创建数据库hourse: 1&#xff1a;关注表 CREATE TABLE guanzhu ( id int(11) NOT NULL AUTO_INCREMENT, uid int(11) DEFAULT NULL, hid int(11) DEFAULT NULL, time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEI…

基于S3C4510B的一个简单BSP的开发报告

系统环境 &#xff08;一&#xff09; 硬件环境 CPU&#xff1a;S3C4510B SDRAM:W981216DH 16M FLASH:MX29LV160AB 2M &#xff08;二&#xff09; 软件环境 tornado2.01 for arm&#xff08;AKA的FTP上有tornado2.2需要的可以自己去下载&#xff1a;&#…

Java项目:房屋租赁管理系统(java+SSM+Layui+Maven+Mysql+Jsp)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 一、项目简述 功能包括&#xff1a; 房屋租赁管理系统是一款方便快捷&#xff0c;易操作的租房和各种物业收费的管理系统&#xff0c;该系统官网包含着用户和管理员分类登录&#xff0c;减少了为使用管理员…

sdtz技术组成

发送短信数据库表到第二天就删除前一天的的内容重新建表是用触发器功能实现的 回款、发标、发短信一些核心功能是用windows服务运行在服务器上自动运行的 sql管理中的维护计划就能设置自动备份数据库转载于:https://www.cnblogs.com/zheng510ke/p/4562812.html

13个 ASP.NET MVC 的扩展

ASP.NET MVC设计的主要原则之一是可扩展性。处理管线&#xff08;processing pipeline&#xff09;上的所有&#xff08;或大多数&#xff09;东西都是可替换的。因此&#xff0c;如果您不喜欢ASP.NET MVC所使用的约定&#xff08;或缺乏某些约定&#xff09;&#xff0c;您可以…

javascript实例

数组排序 ①冒泡排序 思路&#xff1a; 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。对每一对相邻元素作同样的工作&#xff0c;从开始第一对到结尾的最后一对。在这一点&#xff0c;最后的元素应该会是最大的数。针对所有的元素重复以上的步骤&#xff…

Ubuntu10.04安装Flash插件

1. 从Adobe下载Flash安装程序&#xff0c;并且解压。 tar -xzvf install_flash_player_10_linux.tar.gz 2. 把解压出来的“libflashplayer.so” 复制到 /usr/lib/mozilla/plugins 目录下。 sudo cp libflashplayer.so /usr/lib/mozilla/plugins 3. 执行以下命令&#x…

Java项目:健身俱乐部管理系统(java+SSM+Mysql+Jsp)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 项目介绍&#xff1a; 基于jspmysqlSpringmybatis的SSM健身房管理系统 运行环境: jdk 1.8 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA都可以 tomcat环境&#xff1a; Tomcat 7.x,8.x,9.x版本均可&#xf…

通过代理进行页面传值

A 页面跳转到 B页面&#xff0c;在关闭B页面的时候想将B页面的某些内容回传给A页面 在B页面写代理的相关方法 protocol 控制器的名称 Delegate <NSObject> optional -(void) xxxxxx:(控制器 *) control end interface 控制器 : UIViewController property (weak,nonatom…

Linux系统下如何安装软件包

现在一般是使用 RPM &#xff0c;YUM 和 APT 来管理软件包。软件包常用的也就是&#xff0c;查找软件包&#xff0c;安装&#xff0c;卸载&#xff0c;升级。这几个功能。RPM 比较经典&#xff0c;但是也比较麻烦&#xff0c;尤其是在软件依赖关系上面&#xff0c;有的时…

自己设计大学排名-数据库实践

今天我们来学习以下有关于数据提取以及数据库的一些知识&#xff0c; 我们知道其实数据库是一个非常神奇的存在&#xff0c;它是是按照 数据结构来组织、 存储和管理数据的仓库 我们可以使用它对数据进行储存和管理&#xff01; 下面是有关于sqlite3的学习&#xff0c;SQLite3 …

Windows 和 Linux 应用程序从上到下调用层次比较

刚毕业的时候&#xff0c;做了将近一年的Window下的程序开发&#xff0c;主要用MFC&#xff0c;那是也不明白程序在操作系统角度从上到下的整个调用层次。遇到调用库函数&#xff0c;不明白&#xff0c;就查MSDN&#xff0c;每个月1500行代码左右&#xff0c;那时以为这就是软件…

Java项目:药品管理系统(java+swing+Gui+mysql)

源码获取&#xff1a;博客首页 "资源" 里下载&#xff01; 功能介绍&#xff1a;用户管理、药品库存管理、进销管理、营销管理、药品购入、药品售出、药市信息 系统主页&#xff1a; SuppressWarnings("serial") public class SystemMainView extends JFr…