【C基础知识】volatile知识大全

【0】概述

volatile 是易变的、不稳定的意思。很多人根本就没见过,不知道它的存在。

volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释有点误导人;“易变”是因为外在因素引起的,像多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。

volatile 是C语言的关键字之一,是一个类型修饰符(type specifier)。用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

嵌入式程序员经常同硬件、中断、RTOS等打交道,所有这些都要求用到 volatile变量。不懂得volatile内容将会带来灾难。

【1】作用

volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

简单地说就是防止编译器对代码进行优化.比如如下程序:

1 XBYTE[2] = 0x56;
2 XBYTE[2] = 0x57;
3 XBYTE[2] = 0x58;

对外部硬件而言,上述三条语句分别表示不同的操作,会产生三种不同的动作,但是编译器却会对上述三条语句进行优化,认为只有XBYTE[2]=0x58(即忽略前两条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一的进行编译并产生相应的机器代码(产生三条代码)。

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

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

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

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

【2】例子

先看看下面的例子:

1 int i = 10;
2 int j = i;//(1)语句
3 int k = i;//(2)语句

这时候编译器对代码进行优化,因为在(1)、(2)两条语句中,i 没有被用作左值。这时候编译器认为 i 的值没有发生改变,所以在(1)语句时从内存中取出 i 的值赋给 j 之后,这个值并没有被丢掉,而是在(2)语句时继续用这个值给 k 赋值。编译器不会生成出汇编代码重新从内存里取 i 的值,这样提高了效率。但要注意:(1)、(2)语句之间 i 没有被用作左值才行。

再看另一个例子:

1 volatile int i = 10;
2 int j = i;
3 int k = i;

volatile 关键字告诉编译器  i 是随时可能发生变化的,每次使用它的时候必须从内存中取出 i的值,因而编译器生成的汇编代码会重新从 i 的地址处读取数据放在 k 中。

这样看来,如果 i 是一个寄存器变量或者表示一个端口数据或者是多个线程的共享数据,就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。

【3】Q&A

Q:

1)一个参数既可以是const还可以是volatile吗?解释为什么。
2); 一个指针可以是volatile 吗?解释为什么。
3); 下面的函数有什么错误:

1 int square(volatile int *ptr)
2 {
3     return *ptr * *ptr;
4 } 

A:

1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3) 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

1 int square(volatile int *ptr)
2 {
3     int a,b;
4     a = *ptr;
5     b = *ptr;
6     return a * b;
7 }  

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

1 long square(volatile int *ptr)
2 {
3     int a;
4     a = *ptr;
5     return a * a;
6 }   
时间: 2024-10-03 23:20:02

【C基础知识】volatile知识大全的相关文章

python基础知识部分练习大全

python基础知识部分练习大全   1.执行 Python 脚本的两种方式 答:1.>>python ../pyhton.py 2. >>python.py   #必须在首行有 #!/usr/bin/env python3 指定执行语言 2.简述位.字节的关系 答:一个字节(byte)=8位(bit)  位为最小的单位 3.简述 ascii.unicode.utf-8.gbk 的关系 ascii:只能表示256个符号 unicode:万国码,各国都有 需要有2位来表示 utf-8

iOS基础——通过案例学知识之LaunchScreen、APPIcon、StatusBar、UIScrollView、UIPageControl

iOS基础--通过案例学知识之LaunchScreen.APPIcon.StatusBar.UIScrollView.UIPageControl 今天要实现的案例效果图 一.LaunchScreen 1.设置程序的LaunchScreen 在项目配置文件中配置启动页,并且在LaunchScreen.storyboard中进行布局 2.设置LaunchScreen时间 //单位:秒 [NSThread sleepForTimeInterval:1.5f]; 二.APPIcon 1.命名规则:iOS

SVG的基础概念等知识,以及SVG与CANVAS的区别

本文主要介绍了SVG的基础概念等知识,以及SVG与CANVAS的区别,最后给出了一个简单示例,方便大家更好的了解SVG可缩放矢量图形.推荐给大家. SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式.SVG是W3C制定的一种新的二维矢量图形格式,也是规范中的网络矢量图形标准.SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式. 什么是SVG? SVG 指

iOS基础——通过案例学知识之UITableView(上)

iOS基础--通过案例学知识之UITableView(上) 对于UITableView的知识点特别多,因为它是iOS用得最多控件之一,我会尽我最大努力和语言的组织,将所有知识点介绍到位,今天要实现的效果图 吐槽 与Android对比,可以说跟ListView的实现几乎一样,跟RecyclerView一模一样 Android写起来似乎比iOS复杂一点,因为iOS大部分都被封装好了,这一点iOS做得好 对于iOS的方法的命名只能说又长又臭 知识点包括 UITableView的UITableViewD

知识图谱基础知识之三——知识图谱的构建过程

前两次介绍了知识图谱的基本概念和知识图谱的构建方式,这次介绍一个知识图谱系统的构建过程. 1 知识图谱的总体构建思路 如图所示,从原始的数据到形成知识图谱,经历了知识抽取.知识融合(实体对齐).数据模型构建.质量评估等步骤. 原始的数据,按照数据的结构化程度来分,可以分为结构化数据.半结构化数据和非结构化数据,根据数据的不同的结构化形式,采用不同的方法,将数据转换为三元组的形式,然后对三元组的数据进行知识融合,主要是实体对齐,以及和数据模型进行结合,经过融合之后,会形成标准的数据表示,为了发现新

[nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

 一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识: EN-nRF51D 开发板使用NRF51822 芯片为nRF51822-QFAA,如下图所示,共有256KBFLASH,256 页,页大小为1024 字节. NRF51822 内部FLASH 写流程如下: 三.代码解析: main: 1 int main(void) 2 { 3 ... 4 5

[nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM

一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指在一个周期内,信号处于高电平的时间占整个信号周期的百分比,方波的占空比是50%. 2) 调制频率:周期的倒数. 3) 脉冲宽度:信号处于高电平的时间. 二.nRF51822的PWM产生: NRF51822 通过Timer.PPI 和GPIOTE 的配合实现PWM 的功能,由Timer 产生一个事件,

[nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC

一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻转状态, 即指示灯D1 以8Hz 的速率翻转状态 COMPARE0 中断中点亮指示灯D2 二.nRF51822的内部RTC结构: NRF51822 有两个RTC 时钟:RTC0,RTC1.两个RTC 均为24 位,使用LFCLK 低频时钟,并带有12 位分频器,可产生TICK.compare 和溢出

linux基础学习笔记——操作大全

作者:liaoyi 更新时间:2014-6-2 ****************基本操作***************** 关机 shutdown -h now    root用户               init 0              root用户halt      root+一般用户poweroff 重启shutdown -r now    root用户init6     root用户reboot            root+一般用户 注意:1.shutdown 比较灵活,可

理解管理信息系统信息是对客观世界各种事物的特征的反映,是关于客观事实的可通讯的知识。 知识,就是反映各种事物的信息进入人们大脑,对神经细胞产生作用后留下的痕迹。知识是由信息形成的。

1.信息与数据的区别是什么? 信息是客观事物属性的反映.是经过加工处理并对人类客观行为产生影响的数据表现形式. 数据是反映客观事物属性的记录,是信息的具体表现形式. 任何事物的属性都是通过数据来表示的.数据经过加式处理之后,成为信息.而信息必须通过数据才能传播,才能对人类有影响. 2.信息与知识的区别是什么? 信息是对客观世界各种事物的特征的反映,是关于客观事实的可通讯的知识. 知识,就是反映各种事物的信息进入人们大脑,对神经细胞产生作用后留下的痕迹.知识是由信息形成的. 3.举一个同一主题不同