映月读书网 > C语言解惑 > 14.6 使用volatile变量 >

14.6 使用volatile变量

volatile影响编译器编译的结果。如果没有volatile关键字,则编译器可能优化读取和存储,即在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时会先把变量读取到一个寄存器中,以后再取变量值时,就直接从寄存器中取值。

volatile则提醒编译器,用它所定义的变量随时都有可能发生变化,因此编译后的程序每次需要存储或读取这个变量的时候,都需要直接从变量地址中读取数据。

【例14.20】分析下面函数能否实现延时的功能。


void delay
(void
)
{
       int i
;
       int result
;
       for
(i=0
; i < 1863
; ++i
)
            result = 12* 35
;
}
  

【分析】不能。编译器知道12*35的结果为420,因此他没有做乘法而是通过优化处理直接给出“result=420”,从而关闭了计时功能。

如果使用两个变量,及声明


int num1 = 12
,num2 = 35
;
  

使用语句


result = num1 * num2
;
  

也是不能实现计时的。一般与编译器的选择开关有关。这里针对一般的情况,因为优化器知道尽管该函数计算了result的值,但它仍然没有做任何处理。因此,无论result是否已经计算过,程序的执行都不会改变。于是,优化器发现如下循环:


for
( i=0
; i < 1863
; ++i
)
{
      result = num1 * num2
;
}
  

就将其优化为:


for
( i=0
; i < 1863
; ++i
)
{
     // Do nothing
}
  

显然,不需要将Do nothing重复420次,因此程序就被优化为:


// No loop needed
{
     // Do nothing
}
  

要阻止优化的方法是将result声明为volatile。但这也没有彻底解决问题,因为优化器很灵敏,它发现正在计算for循环体的


num1 * num2
;
  

时,会把程序优化成只做一次乘法。


int register1 = num1 * num2
;
for
( i=0
; i < 1863
; ++i
)
{
        result = register1
;
}
  

如果都使用volatile,就会克服这个问题。


//
修改后的程序
void delay
(void
)
{
     int i
;
     volatile int result
;
     volatile int num1 = 12
;
     volatile int num2 = 35
;
     for
( i=0
; i < 1863
; ++i
)
     {
             result = num1 * num2
;
     }
}