打印
[综合信息]

C语言中关于关键字volatile的用法

[复制链接]
1918|47
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nomomy|  楼主 | 2023-8-29 23:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

一、volatile关键字原理

提醒编译器,该关键字后面的变量随时会发生改变,在编译后的程序中,存储或读取该变量时,编译器不会对它进行优化处理,会直接从变量内存地址中直接处理数据。从而可以对特殊地址的稳定访问。

二、volatile用法

简单地说就是防止编译器对代码进行优化。比如如下程序:

Dat[2]=0x55;

Dat[2]=0x56;

对外部硬件而言,上述2条语句分别表示不同的操作,会产生2种不同的动作,但是编译器却会对上述2条语句进行优化,认为只有Dat[2]=0x56(即忽略前1条语句,只产生1条机器代码)。如果键入volatile,则编译器会逐一地进行编译并产生相应的机器代码(产生2条代码)。

再举一个例子:

int a = 10;

int b = a;

int c = a;

编译器在执行这段代码时会发现a变量未做相关操作,它会自动把上次读取a的值直接赋值给c,这时如果a是寄存器变量或者端口数据时,就会容易出问题,这时需要添加volatile变量如下:

volatile int a = 10;

int b = a;

int c = a;

这时,每次读取a变量的值都是直接从内存地址中获取。


一般在什么情况出现:

1)并行设备的硬件寄存器

2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

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

一般说来,volatile用在如下的几个地方:
  1) 中断服务程序中修改的供其它程序检测的变量,需要加volatile;

当变量在触发某中断程序中修改,而编译器判断主函数里面没有修改该变量,因此可能只执行一次从内存到某寄存器的读操作,而后每次只会从该寄存器中读取变量副本,使得中断程序的操作被短路。
  2) 多任务环境下各任务间共享的标志,应该加volatile;

在本次线程内, 当读取一个变量时,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当内存变量或寄存器变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致 。
  3) 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

假设要对一个设备进行初始化,此设备的某一个寄存器为0xff800000。for(i=0;i< 10;i++) *output = i;前面循环半天都是废话,对最后的结果毫无影响,因为最终只是将output这个指针赋值为9,省略了对该硬件IO端口反复读的操作。


使用特权

评论回复

相关帖子

沙发
单片小菜| | 2023-8-30 13:33 | 只看该作者
学习了,不错的知识。

使用特权

评论回复
板凳
wangpe| | 2023-8-31 19:28 | 只看该作者
最近一个月看到第五次这个了

使用特权

评论回复
地板
adolphcocker| | 2023-9-7 12:21 | 只看该作者
过度使用 volatile 可能会导致程序性能下降,因为编译器无法进行优化。

使用特权

评论回复
5
wangdezhi| | 2023-9-7 12:27 | 只看该作者
虽然 volatile 可以确保变量的可见性,但它不能解决所有的多线程内存可见性问题。

使用特权

评论回复
6
iyoum| | 2023-9-7 12:33 | 只看该作者
volatile关键字用于表示变量的值可能会随时发生变化,需要特别处理

使用特权

评论回复
7
juliestephen| | 2023-9-7 12:40 | 只看该作者
volatile 主要用于确保变量在多线程或中断上下文中的可见性

使用特权

评论回复
8
lzbf| | 2023-9-7 12:45 | 只看该作者
由于volatile变量的值可能会随时发生变化,因此编译器不能对其进行任何优化,例如常量折叠、死代码删除等。

使用特权

评论回复
9
pmp| | 2023-9-7 12:54 | 只看该作者
虽然volatile可以防止编译器优化掉变量的读取和写入,但是它不能保证这些操作是原子的。

使用特权

评论回复
10
bartonalfred| | 2023-9-7 13:07 | 只看该作者
不同的编译器可能会对volatile有不同的处理方式。因此,在编写跨平台的代码时,需要特别注意这一点。

使用特权

评论回复
11
linfelix| | 2023-9-7 13:17 | 只看该作者
由于volatile变量的值可能会随时发生变化,因此每次读取volatile变量的值时,编译器都需要进行存储操作,以确保读取到的是最新的值。同样,每次写入volatile变量的值时,编译器也需要进行存储操作,以确保写入的值被保存到内存中。

使用特权

评论回复
12
wangdezhi| | 2023-9-7 13:41 | 只看该作者
由于volatile变量的值可能会随时发生变化,因此不能将其作为函数参数或者函数返回值,因为函数调用时可能会对其进行缓存,从而导致错误的结果。

使用特权

评论回复
13
albertaabbot| | 2023-9-7 13:47 | 只看该作者
在这种情况下,使用 volatile 可以确保编译器不会进行假定,从而避免意外的行为。

使用特权

评论回复
14
wengh2016| | 2023-9-7 13:53 | 只看该作者
不同的编译器可能对 volatile 的实现略有不同。

使用特权

评论回复
15
wangdezhi| | 2023-9-7 14:14 | 只看该作者
由于 volatile 关键字会阻止编译器进行优化,因此在不必要的情况下滥用 volatile 可能会导致性能下降。应该根据具体情况谨慎使用 volatile 关键字。

使用特权

评论回复
16
albertaabbot| | 2023-9-7 14:19 | 只看该作者
在使用 volatile 关键字时,要确保理解你所使用的编译器的行为,以避免潜在的问题。

使用特权

评论回复
17
zerorobert| | 2023-9-7 14:33 | 只看该作者
编译器在优化代码时,可能会对一些变量进行优化,例如将变量缓存在寄存器中,而不是每次都从内存中读取。但对于volatile变量,编译器会禁止这种优化,确保每次都从内存中读取该变量的值。

使用特权

评论回复
18
yeates333| | 2023-9-7 14:54 | 只看该作者
在使用volatile时需要谨慎,确保正确地使用和声明变量,以避免可能导致的数据竞争或内存泄漏等问题。

使用特权

评论回复
19
loutin| | 2023-9-7 15:01 | 只看该作者
不要将volatile用于对变量的操作顺序进行控制。因为volatile只能保证对单个变量的访问是原子的,无法保证多个volatile变量之间的操作顺序。

使用特权

评论回复
20
ccook11| | 2023-9-7 15:11 | 只看该作者
volatile关键字声明的变量是线程安全的,即多个线程可以同时访问该变量,而不会导致数据竞争或内存泄漏等问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

1214

帖子

0

粉丝