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
;
}
}