C语言中的volatile

痴心易碎 提交于 2020-01-05 04:49:47

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 就是在此种情况下使用。  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!