C语言中volatile关键字的学习

来源:互联网 发布:与樱井知香合作的男优 编辑:程序博客网 时间:2024/06/05 22:48

背景:

最近在学习STM32L152芯片,看到对应的HAL库中经常见到volatile关键字,对该关键字不是很明白,所以总结一下该关键字的使用。

学习内容记录:

volatile单词的意思:易变的。在学习volatile之前,先简单理解一下编译器的优化。如下例:

uint8_t i;

i=0;

i=1;

i=2;

这段程序中,编译器可能会认为只有i=2;这句才有意思,把i存储在某个寄存器中,当要使用i时从这个寄存器读取数据,若i由于中断或多线程而使i的变量地址的数据改变,那么读取i的值可能就不一致,进而导致程序运行错误。

volatile关键字就可以避免上述错误的出现,提高代码的鲁棒性,也体现了程序员必备的一种基本功。

volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

下面以stm32的HAL库中的例子继续讲解volatile关键字,如定时器结构体中寄存器的定义


继续go to definition of '_IO'如下;


可以看到_IO定义语句中后面的关键字,指明在寄存器的映射中,寄存器中的数据也是易改变的。

下面以一个实例说明volatile关键字的使用。

uint8_t Flag;

int main()

{

...

while(1)

{

if(Flag==1)

do();

}

}

void TIM_IRQHandler(void)
{
...
Flag=1;
}

上述函数的功能是当发生定时器的中断时,把Flag置1,while(1)循环中检测到Flag 的值改变为1,便会去执行自己的程序do();

需要注意的是,没有volatile也可能能正常运行,但是可能修改了编译器的优化级别之后就又不能正常运行了。因此经常会出现debug版本正常,但是release版本却不能正常的问题。所以为了安全起见,只要是等待别的程序修改某个变量的话,就加上volatile关键字。修改后的程序如下:

volatile uint8_t Flag;

int main()

{

...

while(1)

{

if(Flag==1)

do();

}

}

void TIM_IRQHandler(void)
{
...
Flag=1;
}

总结:

volatile 关键字提醒编译器定义的变量是易变的,编译后的程序每次需要存储或读取该变量时,会直接从变量地址读取数据。在中断或多线程中使用volatile关键字可以避免不同优化等级时程序出错,提高程序的鲁棒性。



原创粉丝点击