浅谈关键字volatile

前言

volatile关键字是c/c++语言中的一种类型修饰符,他的作用是保证内存的可见性

volatile的作用 :

volatile提醒编译器他后面所定义的变量随时都有可能改变,因此编译后的程序每次
需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。若没有此关键字
则编译器可能优化读取和存储,可能暂时使用寄存器中的值,此时如果内存中的值被
修改,内存中数据和寄存器中数据就会不一致导致程序没有达到预期的结果,所以遇
到volatile声明的变量,编译器对访问该变量的代码不再进行优化,每次都要从内存
中去读取,从而可以提供对特殊地址的稳定访问。

volatile的应用举例

给出一个小程序

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
int num = 10;
int* p = (int*)&num;
*p = 20;
printf("num = %d ",num);
return 0;
}

运行后可以看到结果为 num = 20
这是通过指针改变了整型num的值
我们将程序更改一下

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
const int num = 10;
int* p = (int*)&num;
*p = 20;
printf("num = %d ",num);
return 0;
}

在运行后发现 num = 10;
(此处声明一下指针是可以从地址改变由const修饰的整型的值的,后面会演示)
继续修改程序,加上volatile

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
volatile const int num = 10;
int* p = (int*)&num;
*p = 20;
printf("num = %d ",num);
return 0;
}

此时运行程序我们发现 num = 20

总结解释说明

为什么会出现上述的情况呢,其实加上const之后当程序开始运行,程序便默认 num是不能被修改的 ,所以将num的值放入了寄存器中 , 而实际上*p = 20 改的是内存里的值而寄存器里的值是没有被更改的,这就导致了内存与寄存器中值的不等,而当输出num时编译器为了优化整个程序便从寄存器中
取出了num的值,即先前保存在寄存器中的10,所以输出的结果为10。而在加上了关键字volatile之后,便阻止了编译器为了提高速度将一个变量缓存到寄存器内而不写回,表明了该变量是经常变化的,不得被缓存,每次的访问都从内存中访问,从而保证了内存的可见性,所以再次输出为 num = 20。