关键字volatile

一. volatile是什么?

volatile关键字是一种类型修饰符,对于用它声明的类型变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。通常这些变量可能被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。

这是 BS 在 "The C++ Programming Language" 对 volatile 修饰词的说明:

A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.

不使用volatile关键字时,编译器进行优化(举例)
int i=5;
int a=i;
··· ···
int b=i;

编译器发现两次从i读数据的代码之间,并没有对i进行过操作,它会自动把上次读的数据放在b中,而不是重新从i里面读;

使用volatile关键字
volatile int i=5;
int a=i;
··· ···
int b=i;

volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中。
由上述可知,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。

二. volatile的起源

volatile关键字最早出现于20世纪70年代,被用于处理memory-mapeed I/O (MMIO)带来的问题。一块内存地址,既有可能是真正的内存,也有可能被映射到一个I/O端口。所以,每读写一个内存地址,既有可能读写一块数据内存,也有可能读写的是一个I/O设备。
MMIO为什么需要引入Volatile关键词?考虑以下代码执行后a,b,*p的值:

unsigned int *p=GetMagicAddress();
unsigned int a,b;
a=*p;                                              (1)
b=*p;                                              (2)

*p=a;                                              (3)
*p=b;                                              (4)
分析代码:

在此代码片段中,指针p既有可能指向一个内存地址,也有可能指向一个I/O设备。如果指针p指向的是I/O设备,那么(1),(2)中的a,b,就会接收到I/O设备的连续两个字节。但是,p也有可能指向内存,此时,编译器的优化策略,就可能会判断出a,b同时从同一内存地址读取数据,在做完(1)之后,直接将a赋值给b。对于I/O设备,需要防止编译器做这个优化,不能假设指针b指向的内容不变——易变性。

同样,代码(3),(4)也有类似的问题,编译器发现将a,b同时赋值给指针p是无意义的,因此可能会优化代码(3)中的赋值操作,仅仅保留代码(4)。对于I/O设备,需要防止编译器将写操作给彻底优化消失了——”不可优化”性。

对于I/O设备,编译器不能随意交互指令的顺序,因为顺序一变,写入I/O设备的内容也就发生变化了——”顺序性”。

基于MMIO的这三个需求,设计出来的C/C++ volatile关键词,所含有的特性:易变性,不可优化性和顺序性。

三.哪些情况,改变了内存中变量的值,编译器不知道?

1.多线程应用中被几个任务共享的变量;
2.一个中断服务子程序中会访问到的非自动变量;
3.并行设备的硬件寄存器(如:状态寄存器);

四.何时需要使用volatile这个关键字?

嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用会经常要求定义为volatile类型的变量。

五.3个经典的volatile问题

  1. 一个参数既可以是const还可以是volatile吗?解释为什么。
  2. 一个指针可以是volatile 吗?解释为什么。
  3. 下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:

1). 可以是。例如对于只读的状态寄存器而言,如果它仅仅是volatile类型,那么它还是可能被意想不到的改变。但它还是const的时候,程序就不应该试图去修改它。
2). 可以是的。
尽管这种情况并不常见,但它还是可以。一个例子就是:
当一个中断服务子程序企图去修改一个指向一个buffer指针的时候。
3). 这段代码可能有点恶作剧的味道。但它很好说明volatile类型参数的含义和作用。
这段代码的目的是用来返回指针*ptr所指向的值的平方,
但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。所以,这段代码可能返回的不是你所期望的平方值!正确的代码如下:

long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
参考文章

http://hedengcheng.com/?p=725#_Toc373765728
http://blog.csdn.net/littletigerat/article/details/6439413
http://baike.baidu.com/link?url=7yD8aEhVJZaV83DhVKI9B_YkChlOCVSjPl3QnQDzQj7utDb53E-KTaIKbMoxdyLgwjSljttdPfH3MzafX2BZke5fdEP-tXeP8fk0CfT4owe
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容