• C语言中的volatile关键字


    说明:

               volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

        简单地说就是防止编译器对代码进行优化。
     
        大致原因如下:

          因为从寄存器取值比从内存取值快很多。

          所以编译器它就觉得能优化,就把一个变量放在寄存器中。以后取这个变量就在寄存器取就行了。内存里那个数怎么变就无所谓了。

          所以volatile的作用就是告诉编译器,别优化我这个变量。

        举个例子:

    int i =0 ;
    i=1;
    i=2;
    i=3;
    i=4;
    i=5;

      编译器会觉得,你上面那些都是废话,最后优化后,只剩下:

    int i =0;
    i=5;

      

      volatile意思是“易变的”,让编译器不要动它,依然从内存中读取,不要进行任何优化。

        

     一般说来,volatile用在如下的几个地方:

    1. 中断服务程序中修改的供其它程序检测的变量需要加volatile;
    2. 多任务环境下各任务间共享的标志应该加volatile;
    3. 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义

     

          场景:中断服务程序

      
     1 static int i=0;
     2 void main(void)
     3 {
     4      ...
     5      while (1)
     6      {
     7 
     8         if (i)
     9         dosomething();
    10       }
    11 12 
    13 /* Interrupt service routine. */
    14 void ISR_2(void)
    15 {
    16       i=1;
    17 }

      程序的本意是希望ISR_2中断产生时,在main函数中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。

      如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

    一些问答:
    1). 一个参数既可以是const还可以是volatile吗?解释为什么。
     
      答: 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
     
     
    2). 一个指针可以是volatile 吗?解释为什么。
     
      答:是的。尽管这并不很常见。一个例子是当一个中断服务子程序修改一个指向一个buffer的指针时。
     
     
     
     
    3). 下面的函数被用来计算某个整数的平方,它能实现预期设计目标吗?如果不能,试回答存在什么问题:
    1
    2
    3
    4
    int square(volatile int *ptr){
        return ((*ptr) * (*ptr));
    }
    答案:
     
     
    这段代码是个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码
    1
    2
    3
    4
    5
    6
    7
    int square(volatile int* &ptr)//这里参数应该申明为引用,不然函数体里只会使用副本,外部没法更改
    {
        int a,b;
        a = *ptr;
        b = *ptr;
        return a*b;
    }
    由于*ptr的值可能在两次取值语句之间发生改变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望的平方值!正确的代码如下:
    1
    2
    3
    4
    5
    6
    long square(volatile int*ptr)
    {
        int a;
        a = *ptr;
        return a*a;
    }

      

  • 相关阅读:
    java cp命令
    Ubuntu相关IP配置(转)
    (转)Linux操作系统下VMware的多网卡桥接转换
    Linux问题FAQ1
    hadoop运行常见问题FAQ
    hadoop运行故障问题解决1——datanode节点启动后自动关闭
    Java程序设计9——泛型
    一道灵活的css笔试题
    inherit与auto
    再谈visibility:hidden和display:none
  • 原文地址:https://www.cnblogs.com/asam/p/6434472.html
Copyright © 2020-2023  润新知