volatile是一个特征修饰符
(type specifier).volatile的作用是作为指令关键字,
确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
编译器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份
volatile修饰的变量告诉编译器编译器不知道何时会改变,防止编译器根据变量的稳定性做任何优化
说实在的,读到这你可能还是不太明白这个volatile是啥,volatile的意思是在编译器认识的范围外,这个数据可以被改变(可能通过多任务、多线程或者中断处理)。
如果编译器已经将数据读进寄存器,而且与寄存器没有接触。一般情况下,不需要再读这个数据。但是volatile修饰的编译器就不能进行这样优化。
我们现在来看一个代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int g_val = 1;
void sigcb(int signo)
{
g_val = 0;
}
int main()
{
signal(2,sigcb);
while(g_val)
{
}
return 0;
}
我们ctrl c ,这段程序是一定能终止的,但是如果我们加上优化选项
gcc -O2 volatile.c
这就退出不掉了
因为后续再while循环的过程中并不是从内存中拿数据,而是从寄存器中拿数据,编译器进行优化程度越高,某种程度上来说是为了提高编译效率的,但是会造成错误。
我们使用volatile关键字使内存保持可见性
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
volatile int g_val = 1;
void sigcb(int signo)
{
g_val = 0;
}
int main()
{
signal(2,sigcb);
while(g_val)
{
}
return 0;
}
mutable :指定一个特定的数据成员可以在一个const对象中北改变。
class Z
{
int i;
mutable int j;
public:
int f() const();
};
int Z::f()
{
j++; //这是可以的
}