C语言的volatile关键字

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/baidu_35679960/article/details/81710119

使用volatile是禁止编译器对代码进行优化,因为这个变量是易变的。其实这是一个老生常谈的话题了,三个常用的例子就是:
1)并行设备的硬件寄存器(如:状态寄存器)
2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables,如static变量)
3)多线程应用中被几个任务共享的变量

易变是因为外在因素引起的,像中断,像多线程等,
首先说下中断(即上面的第2)个例子)假设有这么一个程序:

static int i = 0;
int main(void)
{
    //...
    while(1)
    {
        if(i)
            dosomething();
    }
}
/*Interrupt service routine.*/
void ISR_2(void)
{
    i=1;
}

程序的本意是希望当ISR_2中断发生时,在main中调用dosomething函数,但是,由于编译器判断在main函数里面没有修改过i,因为可能只执行一次从i到某寄存器的读操作(由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化),然后每次if判断都只使用这个寄存器里面的副本,导致dosomething永远也不会被调用。此时就需要在i变量前加上volatile,来保证对此变量的读写操作都不会被优化。

对于上面的第1)个例子:并行设备的硬件寄存器,例如状态寄存器,某个变量和外部设备的某个状态相对应,当外部设备发生操作的时候,通过驱动程序和中断事件,系统改变了这个变量的值,如果说,我们把这个变量提前缓冲到了cache或者cpu内部的寄存器之中,那么外部设备对这个状态所做的改变我们的程序就无法发现了。

对于第3)个例子,在多线程程序中,多个线程共享的变量,由于多个线程都有可能对这个变量做出修改,所以每次读取变量的时候都要非常小心从内存中去读取才能保证程序的正确性。

猜你喜欢

转载自blog.csdn.net/baidu_35679960/article/details/81710119