C语言中的volatile

1.volatile有什么含义?有什么用法?

官方定义是:

一个变量也许会被后台程序改变。

关键字volatile与const绝对独立。它指示一个变量也许会被某种方式修改,这种方式按照正常程序流程分析是无法预知的(例如,一个变量也许会被一个中断服务程序所修改)。这个关键字使用以下语法定义:

volatile data-defiinition;

注:变量如果加了voletile修饰,则会从内存中重新装载内容,而不是直接从寄存器中拷贝内容。

2.编译器的优化
在本次线程内,当读取一个变量时,为了提高读取速度,编译器进行优化时有时会先把变量读取到一个寄存器中;以后,再读取变量值时,就直接从寄存器中读取;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以保持一致。

当变量因别的线程值发生改变,上面寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

3.常见的问题

(1)说明关键字volatile有什么含意,并给出例子。
 volatile表示被修饰的符号是易变的。告诉编译器不要随便优化我的代码!!
 *一个硬件寄存器
 *中断中用到的变量
 *线程之间共享变量
 volatile int a = 10;
 while((a & 0x01) == 0);
 #define P_UART_STATUS ((const volatile unsigned int *)0x88000000);
       // volatile表示硬件会修改这个寄存器的内容
       // const表示该寄存器只读,写无意义
 (2)一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设
 这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,
 而不是使用保存在寄存器里的备份。
 下面是volatile变量的几个例子:
 1). 并行设备的硬件寄存器(如:状态寄存器)
 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
 3). 多线程应用中被几个任务共享的变量

(3)1). 一个参数既可以是const还可以是volatile吗?解释为什么。

2). 一个指针可以是volatile 吗?解释为什么。
         3). 下面的函数有什么错误:
 int square(volatile int *ptr) {
    return *ptr * *ptr;
  }
 下面是答案:
 1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。
     它是const因为程序不应该试图去修改它。
 2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
 3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,
    由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
 int square(volatile int *ptr) {
   int a,b;
   a = *ptr;
   b = *ptr;
   return a * b;
  }
  由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。
  结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
 long square(volatile int *ptr) {
   int a;
   a = *ptr;
   return a * a;
  }
  Volatile 关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,
  以避免在其中一个线程操作该变量时,将其拷贝入寄存器。
 请看以下情形: A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足
 一定条件(它期待B线程改变变量的值。在此种情况下,当B线程改变了变量的值时,
 已改变的值对其在寄存器的值没有影响。所以A线程进入死循环。
  volatile 就是在此种情况下使用。

原文地址:https://www.cnblogs.com/yangjiquan/p/11368349.html

时间: 2024-10-17 17:02:42

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——让我保持原样

volatile译为:易变的.这不是和题目的让我保持原样矛盾了吗?其实不然,在变量前加上该关键字修饰,确实是告诉编译器,这个变量是一个容易改变的变量,不要对它进行优化,每次都要到变量的地址中去读取变量的数据,但正因为这样,才是保持了变量的原样,因为变量已经发生改变了,你却操作的是没有变化时的数据,这样才让变量失去了本应该保持的属性. eg: int a=1; a=2; a=3; .... 编译器看到这样的代码,会觉得a的值只有a=3才有意义,所以把a存储在一个寄存器中,每次遇到a都在这个寄存器中

转: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