有关volatile关键字的问题

时间:2010-07-16 10:24:08

标签: c++

我知道volatile关键字

volatile int k=7; 

我们提示编译器可以随时更改变量但是简单的是什么 int k=7?我们可以随时更改它,因为它不是恒定的吗?有什么不同?

6 个答案:

答案 0 :(得分:18)

答案 1 :(得分:4)

它主要用于带中断等的低级编程

volatile int count;

void test()
{
   while(count< 100) 
   {
        // do nothing
   }
}

//
// Interrupt function called by the hardware automatically at intervals
//
void interrupt()
{
    count = count + 1;
}

如果你没有将变量声明为volatile,编译器可能会注意到while循环中的count不能改变,所以每次都不会从内存中实际读取值,所以它永远不会退出循环

如果你声明它是volatile,那么编译器每次都会从内存中读取值,因为你告诉它值可能会在没有通知的情况下改变...

另一个用途是映射硬件端口。

在微控制器上,您可能会有一些“出现”在某个存储器地址的数字输入。您可以将它们看作是变量,但当然,根据输入信号,该值可能会一直变化。将值声明为volatile将向编译器表明您确实需要每次都读取此内存位置,因为它可能已更改,并且除非您更改它,否则您不能认为它不会更改。

除非您使用低级别中断或某些线程使用,否则您不需要使用它。

编辑:要清楚,volatile不是标准c ++中的theads之间的同步,它只是必要的一部分。我原帖中的最后一句可能会产生误导。我的文章中关于硬件中断等的例子和内容是volatile的用途,它绝对不是用于线程的,甚至不会尝试使用它。

我最初编写了“线程的一些用法”,因为在某些平台上使用volatile可能就足够了。一般来说这是一个不好的建议,但是如果你有一个核心并且所有“线程”都可以看到所有写入,那么它可能对你有用。例如,在具有基于中断的简单线程切换系统的微控制器上,即使不受标准保护,它也可能“工作”。但是不要这样做。一般情况下这是错误的,c ++ 11有实际工作方式(请记住这个答案是在c ++ 11之前编写的)

答案 2 :(得分:3)

每次编译器遇到对k的访问权限时,它都会从内存中重新获取它,而不是优化代码以折叠它的多次使用。

int k = 7;
int i = k;
int j = k;

等同于:

int k = 7;
int i;
int j;
i = j = k;

volatile int k = 7;
int i = k;
int j = k;

没有。

答案 3 :(得分:1)

易失性强制每次从内存中读取变量而不是缓存它。

答案 4 :(得分:0)

  

我们可以随时更改它,因为它不是恒定的吗?

是的,你可以改变它,但是C ++并没有说明下面会发生什么。这取决于抽象机器(即您正在处理的平台)。

如果volatile变量未映射到HW设备的寄存器,则volatile变量的行为几乎与普通变量相似。我差点说,因为你无法将它传递给期望非易失性int的方法和函数,如下所示:

void foo( int & p );

如果变量映射到HW设备的寄存器,则尝试写入只读寄存器取决于设备。它可能只是忽略写入,但它也可能以某种方式指示错误--c ++不会告诉任何内容。


volatile是一个cv限定符,用于访问硬件寄存器,或者可以在外部修改的部分内存(例如,通过控制器)。

[dcl.type.cv] / 7中的c ++标准告诉:

  

[注意:volatile是一个提示,以避免攻击性   涉及对象的优化因为对象的值   可能会被实现无法检测的方式改变。见1.9   详细的语义。一般来说,volatile的语义是   在C ++中与C语言相同。 - 尾注]

Stay away from Volatile in threaded code?文章讲述了挥发性有利于什么:

  

volatile关键字不是线程或同步原语   在便携式C或C ++中。它主要是为了

     

1)允许访问内存映射设备(即指向可由I / O设备修改的相干内存中数据结构的指针。)
  2)信号处理程序中的变量以及setjmp和longjmp之间的变量(参考:维基百科的易失性)

另一篇文章Volatile: Almost Useless for Multi-Threaded Programming告诉我们:

  

Hans Boehm指出,volatile只有三种可移植用途。我在这里总结一下:
       *在setjmp范围内标记局部变量,以便变量在longjmp之后不回滚        *由外部代理修改的内存或似乎是因为内存映射错误而导致的内存        *信号处理程序恶作剧

  

如果为了速度而进行多线程处理,那么减慢代码绝对不是你想要的。对于多线程编程,有两个关键问题,通常被错误地认为是挥发性的:   *原子性
  *内存一致性,即另一个线程看到的线程操作的顺序。

重要的是,在多线程环境中不应使用volatile 作为同步机制,或者提供原子访问,因为它可能适用于某些编译器,而不适用于其他编译器。为此,还有其他同步工具(例如信号量,或带有条件变量的互斥)和原子访问(atomic library

答案 5 :(得分:0)

Volatile关键字用于通知编译器不要预测/假设/相信/设定已声明为volatile的特定变量的值。

此变量可以通过内部和外部源更改,因此您可以更改它。

const volatile int k = 5; &lt; ====这可能不会被您的程序更改,但可以通过外部源更改,const使其只读,仅适用于编译器或程序员

来源: - Volatile variable in C