zoukankan      html  css  js  c++  java
  • 关键字volatile

      它是被设计用来修饰被不同线程访问和修改的变量如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。

    volatile的作用: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.
    简单地说就是防止编译器对代码进行优化.比如如下程序:
    XBYTE[2]=0x55;
    XBYTE[2]=0x56;
    XBYTE[2]=0x57;
    XBYTE[2]=0x58;
    对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器就不能像对待纯粹的程序那样对上述四条语句进行优化,只认为XBYTE[2]=0x58(即忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一的进行编译并产生相应的机器代码(四条).

      volatile的语法和const是一样的。但是volatile的意思是:“在编译器认识的范围外,这个数据可以改变”。不知何故,环境正在改变数据(可能通过多任务、多线程或者中断处理),所以,volatile告诉编译器不要擅自作出有关该数据的任何假定,优化期间尤其如此。

      就行建立const对象一样,程序猿也可以建立volatile对象,甚至还可以建立const volatile对象,这个对象不能被客户程序猿改变。但是,可以通过外部的代理程序改变。

    #include "stdafx.h"
    
    class Comm
    {
        const volatile unsigned char byte;
        volatile unsigned char flag;
        enum { bufsize = 100 };
        unsigned char buf[bufsize];
        int index;
    
    public:
        Comm();
        void isr() volatile;
        char read(int index) const;
    };
    
    Comm::Comm(): index(0), byte(0), flag(0)
    {
    }
    
    void Comm::isr() volatile
    {
        flag = 0;
        buf[index++] = byte;
        if(index >= bufsize) index = 0;
    }
    
    char Comm::read(int index) const
    {
        if(index<0 || index>= bufsize) return 0;
        return buf[index];
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        volatile Comm port;
        port.isr();// OK
        //port.read(0); //Error read() not volatile
        return 0;
    }

    就像const 一样,我们可以对数据成员和函数成员和对象本身使用volatile,可以对volatile对象调用volitile函数。

    问题: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;
    }
  • 相关阅读:
    Jquery 验证 validate
    JQuery的父、子、兄弟节点查找,节点的子节点循环
    i386、i586、i686、noarch、x86_64
    Java 遍历类中的属性
    页面的缓存与不缓存设置
    JavaScript 判断输入是否为中文的函数
    检查radio/checkbox是否至少选择一项
    JavaScript 检查是否是数字
    JavaScript 检查IP
    Javascript 身份证号获得出生日期、获得性别、检查身份证号码
  • 原文地址:https://www.cnblogs.com/wiessharling/p/2998846.html
Copyright © 2011-2022 走看看