C语言中的volatile——让我保持原样

volatile译为:易变的。这不是和题目的让我保持原样矛盾了吗?其实不然,在变量前加上该关键字修饰,确实是告诉编译器,这个变量是一个容易改变的变量,不要对它进行优化,每次都要到变量的地址中去读取变量的数据,但正因为这样,才是保持了变量的原样,因为变量已经发生改变了,你却操作的是没有变化时的数据,这样才让变量失去了本应该保持的属性。

eg:

int a=1;

a=2;

a=3;

....

编译器看到这样的代码,会觉得a的值只有a=3才有意义,所以把a存储在一个寄存器中,每次遇到a都在这个寄存器中去读取数据,但是a是可能改变,比如中断或者多线程的时候。这个有可能你测试它又是正确的,因为随着你的优化等级提高,生成的汇编代码会有很大不同,如果基础不够扎实,代码的鲁棒性就会减弱,要想不这样,那么需要程序员有足够扎实的基本功。

1.我们先看volatile第一个应用场景,在中断服务函数中的使用。

/*   main.c */

int flag=0;

int main(void)

{

  if(flag==1)

    {do somethings}

  if(flag==2)

        {do somethings}

  return 0;

}

/* interrupt*/

void NVIC_Handler(void)

{

  flag=1;

}

在这种情况下,编译器可能会对其做优化,虽然中断服务函数改变了flag的值,但是编译器并没有在变量内存中去读取,而是在寄存器中读取了flag之前的缓存数据。在中断函数中的交互变量,一定要加上volatile关键字修饰,这样每次读取flag的值都是在其内存地址中读取的,确保是我们想要的数据。

2.多任务环境下各任务间共享的标志应该加volatile。原因其实和上面中断一样,要共享标志,又不想让编译器优化了这一点,需要加上该修饰词。

3.存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义。

以STM32为例,寄存器中的数据也是时刻在变化的,我们也不想编译器优化这一点,所以在库函数中我们可以看到这样的代码。

这是寄存器的结构体,我们查看前缀__I 和__IO到底是什么?

可以看到,在寄存器的映射中,也需要volatile,因为寄存器的值也是可能随时更改的。

通过上面,我们也应该明白那个问题。

一个参数既可以是const还可以是volatile吗?

可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

时间: 2024-10-24 21:51:08

C语言中的volatile——让我保持原样的相关文章

C语言中的volatile关键字

说明: ******一个被volatile关键字修饰的变量可能会被意想不到的改变,本意就是"易变的". ******对于被volatile修饰的变量,当编译器在编译的时候不会去假设该变量的值 ******对于被volatile修饰的变量,当优化器优化时,必须每次都小心的重新读取该变量的值,而不能使用寄存器里的备份. 使用volatile关键字的几种情况: ******第一种情况:并行设备中的状态寄存器(当不同设备访问时,状态可能会随时变化的,所以要用volatile关键字修饰) ***

Java语言中的volatile变量

Java中的两种内置同步机制: synchronized 和 volatile 变量, volatile修饰的变量, 在使用时会强制检查最新值. 有synchronized的值可见性, 但是没有其操作原子性. 因为其轻量的原因, 在一些考虑性能的地方, 可以使用volatile, 但是使用时要非常小心. 常用的场景是: 少写多读, 并且写入口唯一的情况. http://www.ibm.com/developerworks/java/library/j-jtp06197/index.html Us

C语言中的volatile

1.volatile有什么含义?有什么用法? 官方定义是: 一个变量也许会被后台程序改变. 关键字volatile与const绝对独立.它指示一个变量也许会被某种方式修改,这种方式按照正常程序流程分析是无法预知的(例如,一个变量也许会被一个中断服务程序所修改).这个关键字使用以下语法定义: volatile data-defiinition; 注:变量如果加了voletile修饰,则会从内存中重新装载内容,而不是直接从寄存器中拷贝内容. 2.编译器的优化 在本次线程内,当读取一个变量时,为了提高

转:C语言中的static变量和C++静态数据成员(static member)

转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序运行期间,但作用域与自动变量相同,只能在定义该变量的函数内使用.退出该函数后, 尽管该变量还继续存在,但不能使用它.        b.对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值.而对自动变量不赋初值,则其值是不定的.2).static全局变量        全局变量本身就是静

C语言中volatilekeyword的作用

一.前言 1.编译器优化介绍: 由于内存訪问速度远不及CPU处理速度,为提高机器总体性能,在硬件上引入硬件快速缓存Cache,加速对内存的訪问.另外在现代CPU中指令的运行并不一定严格依照顺序运行,没有相关性的指令能够乱序运行,以充分利用CPU的指令流水线,提高运行速度.以上是硬件级别的优化.再看软件一级的优化:一种是在编写代码时由程序猿优化,还有一种是由编译器进行优化.编译器优化经常使用的方法有:将内存变量缓存到寄存器:调整指令顺序充分利用CPU指令流水线,常见的是又一次排序读写指令.对常规内

C语言中setjmp与longjmp学习笔记

一.基础介绍 ?? ?头文件:#include<setjmp.h> ?? ?原型:??int?setjmp(jmp_buf envbuf) ?? ?宏函数setjmp()在缓冲区envbuf中保存系统堆栈里的内容,供longjmp()以后使用.首次调用setjmp()宏时,返回值为0,然而longjmp()把一个变原传递给setjmp(),该值(恒不为0)就是调用longjmp()后出现的setjmp()的值. void longjmp(jmp_buf envbuf,int status);

C++语言学习(五)——C++语言中的CV限定符错误

C++语言学习(五)--C++语言中的CV限定符错误 ?一.CV限定符错误简介 1.CV限定符简介 CV限定符即cv-qualifier,C++语言中指const和volatile限定符.通常,C++语言中有两种情况不能使用CV限定符进行限定:A.非成员函数不能使用CV限定B.静态成员函数不能使用CV限定 2.CV限定符错误信息简介 C++语言中CV限定符错误信息如"cannot have cv-qualifier",常见的CV限定符错误信息如下:A.非成员函数的CV限定符错误信息er

C语言中的32个关键字

C语言中的32个关键字 数据类型关键字(12个) (1)     char:声明字符型变量或函数 (2)     double:声明双精度变量或函数 (3)     enum:声明美剧类型 (4)     float:声明浮点型变量或函数 (5)     int:声明整型变量或函数 (6)     long:声明长整型变量或函数 (7)     short:声明短整型变量或函数 (8)     signed:声明有符号类型变量或函数 (9)     struct:声明结构体变量或函数 (10) 

在Swift语言中,关于Any,AnyObject,AnyClass的区别与联系

在Swift语言中,协议定义类或结构体应该遵守的变量和方法集合,如下所示,这个一个标准的协议的声明: protocol NSObjectProtocol { func isEqual(object: AnyObject?) -> Bool var hash: Int { get } var superclass: AnyClass? { get } func `self`() -> Self! func isProxy() -> Bool func isKindOfClass(aClas