赞
踩
编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以消除一些多余的代码减少占用空间。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化。
//假如定义一个IO地址,IO地址确实需要从0到10依次赋值,写了下面循环。
int *output = (unsigned int *)0xff800000;//定义一个IO端口地址;
int init(void)
{
int i;
for(i=0;i< 10;i++){
*output = i;
}
//上述没定义volatile,编译器会认为你在做些费事,所以最后代码优化等效于
int init(void)
{
int i;
*output = 9;
}
/*
假如外部设备进行初始化的过程是必须是像上面代码一样顺序的对其赋值,显然优化过程并不能达到目的。反之如果你不是对此端口反复写操作,而是反复读操作,其结果是一样的,编译器在优化后,也许你的代码对此地址的读操作只做了一次。然而从代码角度看是没有任何问题的。这时候就该使用volatile通知编译器这个变量是一个不稳定的,在遇到此变量时候不要优化。
*/
//这个函数返回一个数值平方是错误的
int square(volatile int *ptr)
{
return (*ptr) * (*ptr);
}
//编译器优化后产生下面代码,由于*ptr的值可能被意想不到地改变,因此计算过程中a,b的数值可能会改变。
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
//正确代码应该修改为这个
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
int a = 1;
int *ip =&a //设备地址
*ip = 1; //第一个指令
*ip = 2; //第二个指令
//以上程序compiler可能做优化直接将第一个赋值丢了,认为是无效的
int *ip = &a;
*ip = 2;
unsigned char temp = 0x11;
AT24CXX_WriteOneByte(100,0xaa);
temp = AT24CXX_ReadOneByte(100);
main.c(39): warning: #550-D: variable “temp” was set but never used,有了一个提示,那么这个变量肯定是被优化了。因为没有把一个变量当作右值使用,所以优化了。需要定义成 volatile unsigned char temp = 0x11;才可以,证明这个确实需要这样赋值,编译器你千万不要优化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。