看过许多的关于C的笔试题或者面试题,里面都会有提到volatile这个关键字,很多面试的人认为这是区分一般C程序员和嵌入式程序员的一把标尺。其实个人认为volatile 对于一个嵌入式程序员,并不是一个硬性指标。比如本人是做上层路由协议开发,但并没有怎么接触volatile,陌生。但学习C的我们至少应该是抱着越来越的心态: 越来越了解它,越来越多的运用它。
volatile 原意:名词为 挥发物,形容词为 易变的 (来自google翻译)。
一般遇到这个关键词修饰的变量,编译器将对这段代码的访问不进行优化。
编译器的优化,了解的不多。说说我了解到的一点:由于一般访问CPU寄存器比去访问内存要快一点,所以优化编译器一般会把我们定义的变量缓存到寄存器中,以便加速后续的访问。而使用volatile则抑制了编译器的这种优化。
比如下面这个例子。
- #include <stdio.h>
- int main (void)
- {
- volatile int a = 1;
-
- int b = a;
-
- // 这里可以插入其他代码,以一种编译器未知的方式改变a的值。
- int c = a;
- return 1;
- }
这里如果没有volatile修饰 a 那么这句 int b = a; 将是在编译器优化了a(即把a的值缓存到寄存器中)之后,直接从寄存器中读取a的值赋给b, 而不是现在有volatile修饰的需要直接根据a的地址到内存中读取a的值。
代码中的注释告诉我们,如果我们在这里添加一段代码,其用意是修改a的值而不让编译器知道。(这里修改a的值的一种方法是可以用一段汇编代码,可惜我对汇编不懂,是后续的目标)。这时如果a 并没有被volatile修饰,那么int c = a; c的值将是读取了被优化在寄存器中的a的值。而不是我们改变后的真实值。有volatile修饰则避免了这种情况,可以让c得到真实的a的值。
对于volatile的作用应该不止上面这种,以前看到过另外一种作用的描述是这样的:
不做常量合并、常量传播等优化,所以像下面的代码:
volatile int i = 1;
if (i > 0) ...
if的条件不会当作无条件真。
上面这种代码可以理解,但是描述中的常量合并,常量传播不了解是指什么样的情况。
volatile int i = 1;
if (i > 0) ...
if的条件不会当作无条件真。
上面这种代码可以理解,但是描述中的常量合并,常量传播不了解是指什么样的情况。
google了一下可能是这样理解的:
常量合并,是指编译器把一个常量值const int a = 1;直接把a保存在符号表里而不是给a分配空间,以后在需要a的时候直接读取符号表里的1来替换a。
不知道是不是这种理解的,求高手讲解,求正解。