原文链接:https://blog.csdn.net/qrfdt/article/details/119925859
什么是_IO变量:
_IO为volatile变量,volatile 影响编译器编译的结果, 指出:volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错。
volatile(即__IO) 告诉编译器变量是随时可能发生变化的,每次使用它的时候必须从变量的地址中读取,因而编译器生成的可执行码会重新变量的地址读取数据。而如果没有使用__IO,编译器优化做法是,由于编译器发现两次从i中读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中,而不是重新从i里面读。
使用volatile(即__IO)的情况:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义。
加深理解:
例如:volatile表明的是该对象可能会有意想不到的改变,例如从一个寄存器读取温度值,它就会不断的改变,频繁的改变一个变量,C编译器会对其做何种优化?
这段代码的目的是用来返指针ptr指向值的平方,但是,由于ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = ptr;
return a * b;
// 中间ptr的值可能会被寄存器所改变进而导致a,b两个变量不同,得不到a^2这样的结果
}
由于ptr的值可能被意想不到地该变,因此a和b可能是不同的例如可能开始ptr=1,过会*ptr=2了这就会导致a,b两个变量不相同。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
int square(int *ptr)
{
int a,b;
a = ptr;
b = ptr;
return a * b;
// 这样即使ptr在函数体内发生相应改变编译器也会进行优化使得ptr在函数内不会发生改变,最终a,b值相同,这也就是我们所期望的a^2
}
这样的返回值就永远是一个定值的平方了,也就符合本意了。