嵌入式工程师必须知道的变量修饰关键字volatile

volatile定义:

volatile是一个类型修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。

volatile作用:

经过它修饰的变量能防止编译器对其进行优化,

XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;

如果没有用volatile修饰XBYTE[]数组,则编译过后,编译器可能直接认为这里只用执行最终的XBYTE[2]=0x58而在执行程序中只生成一条机器代码,但是如果定义XBYTE[]数组时使用volatile关键字修饰,则编译器编译时,会规规矩矩将这四条指令产生到执行程序里。

volatile使用示例:

使用volatile修饰后的变量,编译器编译时必须每次都小心的重新读取变量的值,而不是使用保存在寄存器里备份的数据。

(1)并行设备的硬件寄存器(如:状态寄存器)

(2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

(3)多线程应用中被几个任务共享的变量

嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所有这些都要求使用volatile变量!

volatile使用地方:

一般说来,volatile用在如下的几个地方:

(1)中断服务程序中修改的供其它程序检测的变量需要加volatile;

(2)多任务环境下各任务间共享的标志应该加volatile;

(3)存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2 中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

volatile相关问题:

(1)一个参数既可以是const还可以是volatile吗?

答:可以,举例说明,只读的状态寄存器,它是volatile因为其可能被意想不到的改变,是const因为程序不应该试图去修改它;

(2)一个指针可以是volatile 吗?

答:可以,不常见,但是有如一个中断服务子程序修改一个指向一个buffer的指针时,可以使用volatile修饰。

(3)下面的函数被用来计算某个整数的平方,它能实现预期设计目标吗?如果不能,试回答存在什么问题:

int square(volatile int *ptr)
{
    return ((*ptr) * (*ptr));
}

答:不能,函数设计的功能应该是返回ptr指针指向的地址的数据的平方值,如上代码可以等同于如下代码:

int square(volatile int* &ptr)//这里参数应该申明为引用,不然函数体里只会使用副本,外部没法更改
{
    int a,b;
    a = *ptr;
    b = *ptr;
    return a*b;
}

由于*ptr的值可能在两次取值语句之间发生改变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望的平方值!正确的代码如下:

long square(volatile int*ptr)
{
    int a;
    a = *ptr;
    return a*a;
}

猜你喜欢

转载自blog.csdn.net/qq_28643619/article/details/88343684