首页 » C语言解惑 » C语言解惑全文在线阅读

《C语言解惑》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;     }}