本篇文章是对C语言中关键字volatile的含义进行了详细的分析介绍,但愿能在学习上帮助你们。程序员
volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不一样线程访问和修改的变量。若是没有volatile,基本上会致使这样的结果:要么没法编写多线程程序,要么编译器失去大量优化的机会。面试
Volatile意思是“易变的”,应该解释为“直接存取原始内存地址”比较合适。“易变”是由于外在因素引发的,像多线程,中断等。编程
C语言书籍这样定义volatile关键字:多线程
volatile提醒编译器它后面所定义的变量随时都有可能改变,所以编译后的程序每次须要存储或读取这个变量的时候,告诉编译器对该变量不作优化,都会直接从变量内存地址中读取数据,从而能够提供对特殊地址的稳定访问。函数
若是没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,若是这个变量由别的程序更新了的话,将出现不一致的现象。(简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以避免出错)性能
通常说来,volatile用在以下的几个地方: 学习
存储器映射的硬件寄存器一般也要加 voliate,由于每次对它的读写均可能有不一样意义。优化
例如:假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。spa
int *output = (unsigned int *)0xff800000;//定义一个IO端口;线程
int init(void)
{
int i;
for(i=0;i< 10;i++){
*output = i;
}
}
通过编译器优化后,编译器认为前面循环半天都是废话,对最后的结果毫无影响,由于最终只是将output这个指针赋值为 9,因此编译器最后给你编译编译的代码结果至关于:
int init(void)
{
*output =9;
}
若是你对此外部设备进行初始化的过程是必须是像上面代码同样顺序的对其赋值,显然优化过程并不能达到目的。反之若是你不是对此端口反复写操做,而是反复读操做,其结果是同样的,编译器在优化后,也许你的代码对此地址的读操做只作了一次。然而从代码角度看是没有任何问题的。这时候就该使用volatile通知编译器这个变量是一个不稳定的,在遇到此变量时候不要优化。
当变量在触发某中断程序中修改,而编译器判断主函数里面没有修改该变量,所以可能只执行一次从内存到某寄存器的读操做,然后每次只会从该寄存器中读取变量副本,使得中断程序的操做被短路。
在本次线程内, 当读取一个变量时,编译器优化时有时会先把变量读取到一个寄存器中;之后,再取变量值时,就直接从寄存器中取值;当内存变量或寄存器变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而形成应用程序读取的值和实际的变量值不一致 。
假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。for(i=0;i< 10;i++) *output = i;前面循环半天都是废话,对最后的结果毫无影响,由于最终只是将output这个指针赋值为9,省略了对该硬件IO端口反复读的操做。
这是区分C程序员和嵌入式系统程序员的最基本的问题:嵌入式系统程序员常常同硬件、中断、RTOS等等打交道,全部这些都要求使用volatile变量。不懂得volatile内容将会带来灾难。
volatile 常见的几个面试题:
能够的,例如只读的状态寄存器。它是volatile由于它可能被意想不到地改变。它是const由于程序不该该试图去修改它。
能够,当一个中服务子程序修改一个指向buffer的指针时。
int square(volatile int*ptr)
{
return*ptr * *ptr;
}
该程序的目的是用来返指针*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;
}
注意:频繁地使用volatile极可能会增长代码尺寸和下降性能,所以要合理的使用volatile。
volatile 关键字是一种类型修饰符,用它声明的类型变量表示能够被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,所以编译后的程序每次须要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如 果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,若是这个变量由别的程序更新了的话,将出现不一致的现象。因此遇到这个关键字声明的变量,编译器对访问该变量的代码就再也不进行优化,从而能够提供对特殊地址的稳定访问。
若是你想更好的提高你的编程能力,学好C语言C++编程!弯道超车,快人一步!
【C语言C++学习企鹅圈子】,分享(源码、项目实战视频、项目笔记,基础入门教程)
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比本身琢磨更快哦!
编程学习书籍:
编程学习视频: