volatile的本意是“易变的”因为访问寄存器要比访问内存单元快得多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据。
当要求使用volatile声明变量值的时候,编译器对访问该变量的代码就不再进行优化,系统总是重新从它所在的内存读取数据。
volatile一般用在以下三种地方:
中断服务程序中 修改的 供其它程序检测的 变量 需要加volatile
volatile int i = 0;
int main(void)
{
while (1)
{
if(i)
do_something();
}
}
/* 中断处理函数 */
void ISR_2(void)
{
i = 1;
}
程序的本意是希望ISR_2中断产生时,在main函数中调用do_something函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致dosomething永远也不会被调用。如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该是volatile int i;
多任务环境下(如多线程)各任务间共享的标志应该加volatile;
外设寄存器地址映射,例如:把寄存器的地址映射到0xff800000
int *output = (unsigned int *)0xff800000;//定义一个IO端口;
int init(void)
{
int i;
for(i=0; i<10; i++)
{
*output = i;
}
}
经过编译器优化后,编译器认为前面循环半天都是废话,对最后的结果毫无影响,因为最终只是将output这个指针赋值为9,所以编译器最后给你编译编译的代码结果相当于:
int init(void)
{
*output = 9;
}