zoukankan      html  css  js  c++  java
  • 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 就是在此种情况下使用。  

  • 相关阅读:
    Java集合之ArrayList
    深入理解Java中的String
    Spring系列之AOP实现的两种方式
    设计模式之代理模式
    使用 Composer 为 ThinkPHP(3.2.3)框架添加和管理组件
    滚动页面, 顶部导航栏固定效果
    nginx同一iP多域名配置方法
    nginx 服务器重启命令,关闭
    CentOS Linux服务器安全设置
    CentOS7安装iptables防火墙
  • 原文地址:https://www.cnblogs.com/yangjiquan/p/11368349.html
Copyright © 2011-2022 走看看