volatile
一、什么是volatile?什么是编译器优化
volatile是一个类型修饰符,它的主要作用是防止编译器进行优化。那么什么是编译器优化呢,我们看两个个例子:
例1:
x = 0x04;
x = 0x06;
x = 0x08;
对于硬件来说这是3条指令,依次执行,但是如果让编译器进行编译,则它会忽略前面两条语句,直接得到 x = 0x08;
int i = 5, j, k;
j = i;
k = i;
编译器进行编译时,由于i在第二条和第三条语句之间没有作为左值存在,所以第三条语句k=i;并没有真正到i所在的内存区域去取得i的值,而是直接取第二条语句保存在寄存器中的副本。
例2:
可见,所谓编译器优化就是假设了某个变量地址,而volatile的作用就是让编译器不去假设变量的值,每次都到内存中小心的去访问变量值。
二、为什么要使用volatile。
尽管前面的例子告诉我们什么是编译器优化,但是编译器优化会产生错误么?如果不会,就不需要防止编译器优化了。
编译器优化是有可能产生错误的。因为上面提到,编译器优化后,对变量取值是有可能会取寄存器中的副本,但是在实际运行时,一些变量的值随时都有可能被一些未知的因素所改变。下面是几种变量的值会被改变,需要用到volatile的情况:
(1)并行设备的硬件寄存器
(2)一个中断子程序会用到的非自动变量
(3)多线程应用中被几个线程用到的共享变量
restrict
首先说明:restrict是c99的关键字,c89和c++均不支持。
restrict用于修饰指针,用来告诉编译器,该指针所指向的对象只能通过该指针访问,让编译器可以进行优化。
比如:
int var = 5; int *restrict varp = &var; *varp = 10; //此行不同 *varp = 20;
编译器会直接优化为:
int var = 5; int *restrict varp = &var; *varp = 20;//<span style="font-family: Arial, Helvetica, sans-serif;">*varp = 10;编译器不处理了。</span>gcc好像需要改变编译器的优化等级(-O),才能实现上述功能。