Chinaunix首页 | 论坛 | 博客
  • 博客访问: 44008
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2015-01-08 10:21
文章分类
文章存档

2016年(1)

2015年(17)

我的朋友

分类: C/C++

2015-01-08 14:29:58

原文地址:关于volatile的详解 作者:FreedomXura

都说"区分volatile"是区分c程序员和嵌入式程序员的标准。不要不屑,如果我问你“请问volatile有什么用?”你能准确的回答吗?
volatile:不稳定的,多变的,反复无常的。
eg:
1.Time is volatile, drum flies with wings.
时间是无常的,鼓着翅膀飞逝。
2.First, tax revenues seem to have become very volatile.
首先,税收收入似乎变得很不稳定。
3.With the markets being so volatile investments are at great risk.
由于市场变化无常,所以现在投资有很大的风险。
OK,英语本意解释完了,看看在c语言中,它到底有什么作用。
volatile作为数据类型(如,int型数据)的修饰语,从本意来看不稳定的,多变的,反复无常的”修饰完数据类型之后,如:

volatile int a;

变量a就被描述成多变的int型变量,这将告诉编译器不要自作多情的对变量a进行优化。
这里有一个疑问,编译器优化?what?
编译器优化:一个变量对应着一个内存地址,为了提高运行速率,编译器会将变量的值读取到某个寄存器中(从寄存器读数据当然比从内存中读数据要快得多),下次读取该变量的值的时候,编译器将直接从这个寄存器读取变量的值,而不到该变量的内存地址处读取值。这将导致什么问题呢?我变量的值已经改变,但是程序读取的变量的值仍然是存放在寄存器中的值,这个值早就over了啊,你还能用吗?
举一个不太准确的例子:  
发薪资时,会计每次都把员工叫来登记他们的银行卡号;一次会计为了省事,没有即时登记,用了以前登记的银行卡号;刚好一个员工的银行卡丢了,已挂失该银行卡号;从而造成该员工领不到工资  

员工 -- 原始变量地址  
银行卡号 -- 原始变量在寄存器的备份(这个值等于原始变量)
更直观一点,看图:

事实说话:

#include <stdio.h> 
void main() 
{ 
int i=10; 
int a = i; 
printf("i= %d\n",a); 
//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道 
__asm { 
mov dword ptr [ebp-4], 20h 
}


int b = i; 
printf("i= %d\n",b); 
} 

Debug模式的时候:

release模式的时候:

输出的结果明显表明,release模式下,编译器对代码进行了优化,第二次没有输出正确的i值。下面,我们把 i的声明加上volatile关键字,看看有什么变化: 

#include <stdio.h> 
void main() 
{ 
volatile int i=10; 
int a = i; 
printf("i= %d\n",a); 

//下面汇编语句的作用就是改变内存中i的值,但是又不让编译器知道 
__asm { 
mov dword ptr [ebp-4], 20h 
} 

int b = i; 
printf("i= %d\n",b); 
}

Debug模式的时候:

 release模式的时候:

即:无论是debug模式还是release模式,输出都是i对应的原始内存的值。这说明这个关键字发挥了它的作用,使得编译器每次读取int变量a的时候都在a的原始内存地址中读取数据,而不在寄存器中读取。

最后一点:volatile一般用在什么地方?

1.用来修饰硬件寄存器。如:

#define rUTXH0 (*(volatile unsigned int *)0x50000020)

2.用来修饰中断子程序中会访问到的非自动变量(Non-automatic variables) 

3.多线程应用中被几个任务共享的变量

总结:

请问你对volatile有什么了解?

--volatile的本意为多变的,用来修饰变量类型,这样就可以避免编译器自作多情的优化所产生的错误后果,使得每次读取变量的值的时候都到变量的内存地址中去读取,而不是到某个寄存器中读数据。

阅读(836) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~