佛山网站建设 奇锐科技,设计公司简介范文,做合约交易哪个网站好,有没有做相册的网站嵌入式C语言中的关键字volatile 嵌入式C语言中的关键字volatile 嵌入式C语言中的关键字volatile一. volatile关键字的概念二. 不使用volatile关键字三. 编译器优化介绍四. volatile详解五. 编译器优化举例1#xff09;例#xff1a;没有volatile关键字的优化2#xff09;例例没有volatile关键字的优化2例volatile关键字对形参的优化 六. volatile关键字使用七. 总结 一. volatile关键字的概念
是作为指令关键字确保本条指令不会因编译器的优化而省略且要求每次直接读值。 volatile关键字是一种类型修饰符用它声明的类型变量表示不可以被某些编译器未知的因素更改优化。volatile提醒编译器它后面所定义的变量随时都有可能改变因此编译后的程序每次需要存储或读取这个变量的时候都会直接从变量地址中读取数据而不是从寄存器或者缓存中去读取数据。
二. 不使用volatile关键字
如果没有volatile关键字则编译器可能优化读取和存储可能暂时使用寄存器中的值如果这个变量由别的程序更新了的话将出现不一致的现象。所以遇到这个关键字声明的变量编译器对访问该变量的代码就不再进行优化从而可以提供对特殊地址的稳定访问。
三. 编译器优化介绍
由于内存访问速度远不及CPU处理速度为提高机器整体性能在硬件上引入硬件高速缓存Cache加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行没有相关性的指令可以乱序执行以充分利用CPU的指令流水线提高执行速度。以上是硬件级别的优化。 再看软件一级的优化一种是在编写代码时由程序员优化另一种是由编译器进行优化。编译器优化常用的方法有将内存变量缓存到寄存器调整指令顺序充分利用CPU指令流水线常见的是重新排序读写指令。 对常规内存进行优化的时候这些优化是透明的而且效率很好。 volatile总是与优化有关编译器有一种技术叫做数据流分析分析程序中的变量在哪里赋值、在哪里使用、在哪里失效分析结果可以用于常量合并常量传播等优化进一步可以消除一些代码。但有时这些优化不是程序所需要的这时可以用volatile关键字禁止做这些优化。
四. volatile详解
volatile的本意是“易变的” 因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化但有可能会读脏数据。当要求使用volatile声明变量值的时候系统总是重新从它所在的内存读取数据即使它前面的指令刚刚从该处读取过数据。精确地说就是遇到这个关键字声明的变量编译器对访问该变量的代码就不再进行优化从而可以提供对特殊地址的稳定访问如果不使用volatile则编译器将对所声明的语句进行优化。简洁的说就是volatile关键词影响编译器编译的结果用volatile声明的变量表示该变量随时可能发生变化与该变量有关的运算不要进行编译优化以免出错
五. 编译器优化举例
我们先来看下面的两个例子。
1例没有volatile关键字的优化
int i 10;
int main(void){int a, b;a i;...//伪代码里面不含有对 a 、 b 以及i的操作b i;if(a b){printf(a b);}else {printf(a ! b);}return 0;
}int i 10;
int main(void){int a, b;a i;...//伪代码里面不含有对 a 、 b 以及 i的操作b i;printf(a b);return 0;
}
在仅仅从main主函数来看a b是必然的那么在什么情况a 和 b不是必然相等呢答案如下。
i 是其他子线程与主线程共享的全局变量其他子线程有可能修改 i 值i 是中断函数与主函数共享的全局变量中断函数有可能修改 i 值i 属于硬件寄存器CPU可能通过硬件直接改变 i 的值例如寄存器的标志位 也就说如果满足了上面三个条件中的任何一个那么就有可能出现a!b的情况。这个时候为了防止编译器不必要的优化手段就可以引入关键字volatile。
2例volatile关键字对形参的优化
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 常见的几个问题 1、一个参数既可以是const还可以是volatile吗 可以例如只读的状态寄存器。它是 volatile 因为它可能被意想不到地改变。它是 const 因为程序不应该试图去修改它。 2、一个指针可以是 volatile 吗 可以当一个服务子程序修改一个指向一个 buffer 的指针时 3、C语言编译过程中volatile关键字和extern关键字分别在哪个阶段起作用 volatile应该是在编译阶段extern在链接阶段。 volatile关键字的作用是防止变量被编译器优化而优化是处于编译阶段所以volatile关键字是在编译阶段起作用。
七. 总结
总结一下如果不使用volatile编译器可以更好的为我们优化代码优化为性能或者效率更好的执行代码。但反过来如果频繁地使用volatile很可能会增加代码尺寸和降低性能,因此要合理的使用volatile。 具体在嵌入式开发过程当中有以下两种用法 1告诉compiler不能做任何优化 比如要往某一地址送两指令 代码如下:
int *ip ...; //设备地址
*ip 1; //第一个指令
*ip 2; //第二个指令
以上程序compiler可能做优化而成
int *ip ...;
*ip 2;结果第一个指令丢失。 如果用volatile, compiler就不允许做任何的优化从而保证程序的原意 volatile int *ip …; *ip 1; *ip 2; 即使你要compiler做优化它也不会把两次付值语句间化为一。它只能做其它的优化。这对device driver程序员很有用。 2表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取而不能把他放在cache或寄存器中重复使用。 如复制代码 代码如下:
volatile char a;
a0;
while(!a) { //do some things;
}
doother();
//如果没有 volatile则doother()不会被执行编译器优化a的读取 认为a的值不改变恒为0