C语言中的volatile——让我保持原样
volatile译为:易变的。这不是和题目的让我保持原样矛盾了吗?其实不然,在变量前加上该关键字修饰,确实是告诉编译器,这个变量是一个容易改变的变量,不要对它进行优化,每次都要到变量的地址中去读取变量的数据,但正因为这样,才是保持了变量的原样,因为变量已经发生改变了,你却操作的是没有变化时的数据,这样才让变量失去了本应该保持的属性。
例如:
int a=;
a=;
a=;
....
编译器看到这样的代码,会觉得a的值只有a=3才有意义,所以把a存储在一个寄存器中,每次遇到a都在这个寄存器中去读取数据,但是a是可能改变,比如中断或者多线程的时候。这个有可能你测试它又是正确的,因为随着你的优化等级提高,生成的汇编代码会有很大不同,如果基础不够扎实,代码的鲁棒性就会减弱,要想不这样,那么需要程序员有足够扎实的基本功。
1.我们先看volatile第一个应用场景,在中断服务函数中的使用。
/* main.c */
int flag=;
int main(void)
{
if(flag==)
{do somethings}
if(flag==)
{do somethings} return ;
} /* interrupt*/
void NVIC_Handler(void)
{
flag=;
}
在这种情况下,编译器可能会对其做优化,虽然中断服务函数改变了flag的值,但是编译器并没有在变量内存中去读取,而是在寄存器中读取了flag之前的缓存数据。在中断函数中的交互变量,一定要加上volatile关键字修饰,这样每次读取flag的值都是在其内存地址中读取的,确保是我们想要的数据。
2.多任务环境下各任务间共享的标志应该加volatile。原因其实和上面中断一样,要共享标志,又不想让编译器优化了这一点,需要加上该修饰词。
3.存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义。
以STM32为例,寄存器中的数据也是时刻在变化的,我们也不想编译器优化这一点,所以在库函数中我们可以看到这样的代码。
这是寄存器的结构体,我们查看前缀__I 和__IO到底是什么?
可以看到,在寄存器的映射中,也需要volatile,因为寄存器的值也是可能随时更改的。
通过上面,我们也应该明白那个问题。
一个参数既可以是const还可以是volatile吗?
可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。软件不能改变,并不意味着我硬件不能改变你的值,这就是单片机中的应用。
C语言中的volatile——让我保持原样的更多相关文章
- C语言中的volatile关键字简介
C语言中的volatile关键字简介: (1)含义: volatile关键字的意思是可能会被外来的意想不到的改变.它的作用是:优化器在使用该关键字定义的变量时,直接从内存中读取原始的数 ...
- Java语言中的volatile变量
Java中的两种内置同步机制: synchronized 和 volatile 变量, volatile修饰的变量, 在使用时会强制检查最新值. 有synchronized的值可见性, 但是没有其操作 ...
- C语言中的volatile
转自C语言的那些小秘密之volatile volatile的重要性对于搞嵌入式的程序员来说是不言而喻的,对于volatile的了解程度常常被不少公司在招聘嵌入式编程人员面试的时候作为衡量一个应聘者是否 ...
- C语言中volatile的作用和使用方法
在程序设计中,尤其是在C语言.C++.C#和Java语言中,使用volatile关键字声明的变量或对象通常具有与优化.多线程相关的特殊属性. 通常,volatile关键字用来阻止(伪)编译器认为的无法 ...
- C++中函数的默认参数和C语言中volatile的学习
1.函数默认参数 1 int func(int a,int b=10) 2 { 3 return a*b; 4 } 5 6 int main() 7 { 8 int c=func(2); 9 cout ...
- 转:C语言中的static变量和C++静态数据成员(static member)
转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量 a.静态局部变量在函数内定义,生存期为整个程序 ...
- C语言中setjmp与longjmp学习笔记
C语言中setjmp与longjmp学习笔记 一.基础介绍 头文件:#include<setjmp.h> 原型: int setjmp(jmp_buf envbuf) ,然而longjm ...
- C语言中的32个关键字
C语言中的32个关键字 数据类型关键字(12个) (1) char:声明字符型变量或函数 (2) double:声明双精度变量或函数 (3) enum:声明美剧类型 (4) ...
- C语言中,头文件和源文件的关系(转)
简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析阶段 3.编译阶段,首先编译成纯汇编语句, ...
随机推荐
- keil_4/MDK各种数据类型占用的字节数
笔者正在学习uCOS-II,移植到ARM时考虑到数据类型的定义,但对于Keil MDK编译器的数据类型定义还是很模糊,主要就是区分不了short int.int.long 和long int占用多少字 ...
- Android 开发环境配置图文教程(jdk+eclipse+android sdk)
一 相关下载(1) java JDK下载:进入该网页: http://java.sun.com/javase/downloads/index.jsp (或者直接点击下载)如下图: 选择 Downloa ...
- POJ 2823 Sliding Window(单调队列 || 线段树)题解
题意:求每个长度为k的数组的最大值和最小值 思路: 1.用线段树创建维护最大值和最小值,遍历询问,简单复习了一下...有点手生 2.单调队列: 可以看一下详解 单调队列顾名思义就是一个单调递增或者递减 ...
- Nginx 负载均衡的几种方式
如果Nginx没有仅仅只能代理一台服务器的话,那它也不可能像今天这么火,Nginx可以配置代理多台服务器,当一台服务器宕机之后,仍能保持系统可用.具体配置过程如下: 1. 在http节点下,添加ups ...
- java编程内容之开始
java应用程序开发应该掌握的各方面技术 1.初识java,熟悉Eclipse开发工具 2.java语言基础 3.流程控制,数组,字符串,类与对象 4.接口,继承与多态,类的高级特性 5.Java集合 ...
- 怎么彻底删除2345的各种顽固Process
清晨打开电脑,都是2345的不良新闻,心情不美美哒 2345如何卸载? “C:\Windows\System32\drivers”目录删除Mslmedia.sys 开始-运行-cmd输入“sc del ...
- 团队作业7—团队项目设计完善&编码测试
一.根据OOD详细设计工作要点,修改完善团队项目系统设计说明书和详细设计说明. <软件设计方案说明书>Github仓库地址:https://github.com/RNTF6/web 完善内 ...
- angular组件层次与军事指挥层级职责的联系
又继续读angular文档,发现自己之前理解还是有误.按官方文档的思路service不是属于component的,是属于module的.module才是负责完整领域逻辑的单位.demo的英雄编辑器给我 ...
- Codeforces 919D - Substring
919D - Substring 思路: 拓扑排序判环+DAG上dp+记忆化搜索 状态:dp[i][j]表示以i为起点的路径中j的最大出现次数 初始状态:dp[i][j]=1(i have no so ...
- R & ggplot2 & Excel绘图(直方图/经验分布图/QQ图/茎叶图/箱线图)实例
持续更新~ 散点图 条形图 文氏图 饼图 盒型图 频率直方图 热图 PCA图 3D图 火山图 分面图 分面制作小多组图 地图 练习数据: year count china Ame jap '12 2. ...