volatile关键字

在C和C++中,volatile关键字用于告诉编译器某些特定的变量可能会在无意中被修改,从而防止编译器优化掉相关代码。当我们使用声明为volatile类型的变量时,表示变量的值是随时可能发生变化的,并且需要特别小心地处理。

主要有以下几种情况需要使用volatile关键字:

  1. 位域
    当使用volatile关键字定义位域时,保证相应的存储单元不被优化器优化,并且在访问每个位域时都会从该内存位置重新读取数据。由于位域只能定义为整型或枚举类型,因此如果一个结构体里面有位域成员,需要将整个结构体定义为volatile类型才能保证可靠性。

  2. 中断服务程序中修改的变量
    在一些嵌入式系统中,硬件设备产生中断信号后,中断服务程序需要马上执行,这时需要使用volatile关键字来声明中断服务程序修改的变量,以免编译器优化掉相关代码。

  3. 多线程环境中被多个线程共享的变量
    当多个线程访问同一个变量时,各线程之间对共享变量进行的操作可能不遵循程序的代码顺序,如果没有使用volatile关键字,编译器可能会进行代码重排,导致程序运行结果与预期不符。

综上所述,volatile关键字的作用是告诉编译器某个变量是易变的,需要特殊处理,以便正确地反映该变量在程序中的实际状态,避免因优化掉相关代码而引发的不可预期的问题。

举个例子:
下面是一个在嵌入式系统中的使用volatile关键字的例子:

#include <stdio.h>

// 定义一个计时器
volatile unsigned int timer = 0;

// 模拟硬件中断服务程序,每隔一秒钟定时器值加1
void interrupt_service_routine() {
    while (1) {
        // 将定时器值加1
        timer++;
        // 模拟延时
        for (int i = 0; i < 0xFFFFF; i++);
    }
}

// 主函数,定时查询定时器的值
int main() {
    // 启动中断服务程序
    interrupt_service_routine();

    // 定时查询定时器的值并输出
    while (1) {
        printf("Timer = %u\n", timer);
        // 模拟延时
        for (int i = 0; i < 0xFFFFF; i++);
    }

    return 0;
}

在上面的代码中,我们定义了一个volatile类型的变量timer,表示这个变量可能会被不同线程或中断服务程序所修改。然后,我们在一个死循环中不停地查询这个变量的值并输出,在主循环中也增加了一个模拟延时的操作。

而在interrupt_service_routine()函数中,则通过一个死循环不停地将timer变量的值加1,模拟每隔1秒钟就会产生中断并对该变量进行修改的情况。

因为timer是一个易变的变量,可能被interrupt_service_routine()函数随时修改,因此我们需要在声明该变量时使用volatile关键字来告诉编译器进行特殊处理,并保证查询到的值是实际的最新值,避免了不可预期的运行结果。

posted @ 2023-04-10 13:05  榴红八色鸫  阅读(43)  评论(0编辑  收藏  举报