首页 > 编程知识 正文

c语言易变的变量的关键字,c语言volatile场景

时间:2023-05-03 15:52:00 阅读:145478 作者:3881

一.前言

1 .编译器优化介绍:

内存访问速度远远不及CPU的速度,因此为了提高机器的整体性能,在硬件上部署硬件缓存Cache以加快内存访问速度。 在现代CPU中,指令的执行不一定严格按顺序执行,不相关的指令可以按顺序执行,以充分利用CPU的指令流水线来提高执行速度。 以上就是硬件级别的优化。 让我们来看看软件级别的优化。 一个是编写代码时程序员优化,另一个是编译器优化。 编译器优化的常用方法是将内存变量缓存在寄存器中; 要调整指令的顺序,请充分利用CPU指令流水线。 常见的是更改读写命令的顺序。 在优化常规内存时,这些优化是透明高效的。 由编译器优化或硬件排序引起的问题的解决方案是在硬件(或其他处理器)必须以特定顺序执行的操作之间设置内存屏障。 linux提供了解决编译器执行顺序问题的宏。

是语音信箱(语音)

此函数通知编译器插入内存屏障,但对硬件无效。 编译后的代码将当前CPU寄存器中所有更改的值存储在内存中,并在需要这些数据时从内存中重新读取。

2.volatile始终与优化相关。 编译器有一种叫做数据流分析的技术。 解析器中的变量在哪里赋值、在哪里使用、在哪里无效? 分析结果可用于常数耦合、常数传播等优化,还可以消除一些代码。 但是,程序可能不需要这些优化。 在这种情况下,可以使用volatile关键字禁止这些优化。

二、volatile详细说明:

1 .原理作用:

volatile的原意是“容易改变”。 由于对寄存器的访问比对存储单元的访问要快得多,所以编译器一般会进行减少访问存储器的优化,但可能会读取脏数据。

如果需要使用volatile声明变量值,系统将始终从该内存中重新读取数据,即使前面的指令刚刚从其中读取数据。

确切地说,遇到用该关键字声明的变量后,编译器将不再优化访问该变量的代码,而是直接从变量的内存地址读取数据,从而实现对特殊地址的稳定访问。 如果不使用valatile,编译器将优化声明的语句。 (简言之,volatile关键字会影响编译器的编译结果,而在volatile中声明的变量表示该变量可能随时发生变化。 有关该变量的运算,请不要进行编译优化,以免发生错误。)

2 .查看两个案例:

告诉计算机无法优化

例如,要向某个地址发送两个命令:

int *ip=; //设备地址

*ip=1; //第一个命令

*ip=2;//第二个命令

上述程序compiler可能已优化。

int *ip=;

*ip=2;

结果中的第一个命令丢失。 使用volatile,compiler不允许优化,并保证程序的原意。

volatile int *ip=;

*ip=1;

*ip=2;

尝试优化compiler时,两个价值语句之间不会存在一个差异。 只能进行其他优化。

在volatile中定义的变量在程序外发生变更,每次都必须从内存中读取,不能重复使用放入cache或寄存器中的备份。

以下是使用volatile变量的几个场景:

1在中断服务程序中更改的其他程序检测到的变量中,需要添加volatile;

2在多任务环境下,各任务之间共享的标志应该加上volatile

3一般在内存映射的硬件寄存器中也添加voliate。 这是因为每次读写都可能有不同的意义。

例如:

假设要初始化设备。 此设备的寄存器之一是0xff800000。

int*output=(unsignedint* )0xff800000; 定义一个//IO端口

Int Init (语音) )。

{

int i;

for(I=0; i 10; I ) {

*output=i;

}

}

编译器优化后,编译器认为前面的循环是无稽之谈,不会影响最后的结果。 因为最终只需将指针output赋值为9,所以编译器最后编译的代码结果如下:

Int Init (语音) )。

{

*output=9;

}

很明显,如果初始化此外部设备的过程需要按顺序赋值,如上面的代码所示,则优化过程无法达到目的。 相反,如果对该端口重复读取而不是重复写入,则结果相同。 编译器优化后,代码可能只对此地址进行一次读取。 但是,从代码的角度来看没有任何问题。 在这种情况下,必须使用volatile通知编译器此变量不稳定。 遇到这个变量时不要优化。

例如:

volatile int * output=(volatile unsign

ed int *)0xff800000;//定义一个I/O端口

另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中禁止任务调度,3中则只能依靠硬件的良好设计。

4.几个问题

1)一个参数既可以是const还可以是volatile吗?

可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

2) 一个指针可以是volatile 吗?

可以,当一个中服务子程序修该一个指向一个buffer的指针时。

5.volatile的本质:

1> 编译器的优化

在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。

当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。

2>volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。