Bootstrap

C/C++ volatile 关键字的作用

一、volatile关键字在 C/C++ 中的作用

防止编译器优化
在 C/C++ 中,编译器会对代码进行优化。
例如,当一个变量在一个循环中被频繁读取,并且编译器认为这个变量的值不会在循环过程中改变时,它可能会把这个变量的值缓存起来,而不是每次都从内存中读取。但是对于一些特殊的变量,如硬件寄存器或者被多个线程或中断服务程序访问的共享变量,这种优化是不允许的。
例如,考虑一个简单的程序,它从一个硬件设备的寄存器中读取数据: 

// 假设这是一个硬件寄存器的地址
volatile unsigned int *hardware_register = (volatile unsigned int *)0x1234;
int main() {
    unsigned int value;
    // 从硬件寄存器读取数据
    value = *hardware_register;
    return 0;
}
  • 在这个例子中,volatile关键字告诉编译器,*hardware_register的值可能会在程序不知情的情况下被改变(比如硬件设备更新了寄存器的值),所以编译器每次访问这个变量时都必须从内存(或者硬件寄存器对应的内存地址)中读取,而不能使用缓存的值。
  • 用于多线程或中断程序中的共享变量
    • 当多个线程或者中断服务程序访问同一个全局变量时,这个变量的值可能会在任何时刻被其他线程或中断改变。
    • 例如,假设有一个全局变量shared_variable,它被一个主线程和一个中断服务程序访问:
#include <stdio.h>
#include <signal.h>

volatile int shared_variable = 0;

void signal_handler(int signum) {
    // 中断服务程序中修改共享变量
    shared_variable++;
}

int main() {
    // 注册信号处理函数
    signal(SIGINT, signal_handler);
    while (1) {
        // 主线程中读取共享变量
        printf("Shared variable value: %d\n", shared_variable);
    }
    return 0;
}
  • 在这里,volatile关键字确保了shared_variable的值在主线程每次读取时都是最新的,因为中断服务程序可能随时修改它。如果没有volatile关键字,编译器可能会对shared_variable的读取进行优化,导致主线程无法获取到最新的值。

二、volatile关键字与const关键字的区别

const关键字
const关键字用于定义常量,它告诉编译器这个变量的值是不可以被修改的。一旦一个变量被定义为const,任何试图修改它的操作都会导致编译错误。

例如:

const int constant_variable = 10;
// 下面这行代码会导致编译错误
// constant_variable = 20;
  • const变量通常用于定义一些不会改变的值,比如数学常数(如π的值)或者程序配置参数等。编译器可以利用const变量的值不变这一特性进行优化,例如将使用const变量的表达式在编译时计算出来。
  • volatile关键字与const关键字的对比
    • volatile强调变量的值可能会在程序的控制流之外被改变,所以编译器不能对其进行优化,每次访问都要从内存中获取最新的值;而const强调变量的值不能被程序本身修改。
    • 可以有volatile const类型的变量,这种变量的值不能被程序修改,但是可能会被程序外部(如硬件或其他线程)修改。例如,一个硬件寄存器可能有一个固定的初始值(由硬件设计决定),程序不能修改它(符合const的特性),但是硬件可能会更新它的值(符合volatile的特性):
volatile const int *hardware_register = (volatile const int *)0x1234;

 

 

 

 

 

 

 

 

;