打印
[其它]

单片机volatile关键字的作用

[复制链接]
3615|47
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
rosemoore|  楼主 | 2023-9-28 14:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
volatile修饰的变量是说这变量可能会被意想不到地改变。通常对于程序员而言,单片机中用的就算常见了。

volatile 是易变的,不稳定的意思。其实对于很多人来说,根本没见过这个关键字,不知道它的存在。也有很多人知道它的存在,根本没用过,我对它有种“杨家有女初长成,养在深闺无人识”的感觉。

那么volatile关键字到底是什么意思呢,怎么用呢?

1、volatile其实和const一样是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素而改变,比如操作系统、硬件或者其他线程等等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

①我们举个例子:

int i=10;

int j=i; //①语句

int k=i; //②语句

此时编译器对代码进行优化,这是因为在①、②两条语句中,i没有被用作左值(没有被赋值),这时候编译器认为是i的值没有发生改变,所以在①语句时从内存中取出i的值赋给j之后,这个值并没有被丢掉,而是在②语句时继续用这个值给k赋值。编译器不会生成出汇编代码重新从内存里取i的值(不会编译生成装在内存的汇编指令,比如ARM的LDM指令),这样提高了效率。但要注意①和②语句之间确认i没有被用作左值才行。

②再看一个例子:

volatile int i=10;

int j=i; //③语句

int k = i; //④语句

volatile关键字告诉编译器,i是随时可能发生改变的。每次使用它的时候必须从内存中取出i的值,因而编译器生成的汇编代码会重新从i的地址处读取数据放在k中。

这样看来,如果i是一个寄存器变量,表示一个端口数据或者是多个线程的共享数据,那么就容易出错,所以说,volatile可以保证对特殊地址的稳定访问。

2、我们知道做电子方面技术工作的一般面试的时候都有笔试,比如单片机软件方面,考题基本都会有对这个关键字的考察,可想在单片机中这个关键字的重要性,一般题目会有对这个关键字的定义是什么,就是你得知道它的概念,然后就是举例说明这个关键字使用的例子,这个时候就能考察出大家对这个关键字的具体理解了。

一般我们知道的是:

①并行设备的硬件寄存器(比如状态寄存器)

②一个中断服务子程序中会访问到的非自动变量

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



当我们回答出这些时基本可以知道你对这个关键字是懂的,如果做嵌入式的话,程序员经常和硬件、中断、RTOS等等打交道,所以这个关键字必须要懂。

3、那么我们再延伸一下,一个参数既可以是const也可以是volatile,那么举个例子就是只读的状态寄存器,那么只读就是const,并且要确定程序不能试图去修改它,再有就是volatile代表状态寄存器,可能被意想不到的改变。

4、那么指针是不是可以用到这个volatile关键字吗,是可以的。

这个我们只要了解即可,用的不多。但是得知道。举个例子就是当一个中断服务子程序修改一个指向一个buffer的指针的时候。修饰也和const类似,const有常量指针和指针常量的说法,volatile也可以这样认为,比如修饰由指针指向的对象或数据是const或volatile的。

例如:

volatile char *p1;

比如指针自身的值---一个代表地址的整数变量是const或volatile的。

例如:

char* volatile p1;

对于这个关键字不仅C语言有,其他语言比如C++,JAVA其实都有。其他语言大部分是因为多线程共享变量的使用不被编译器优化的错误产生,比如优化编译器把一个变量从内存装入CPU寄存器中,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这回造成程序的错误执行。那么用了volatile来修饰变量了呢就是要告诉编译器每次操作这个变量的时候一定要从内存中真正取出,而不是使用已经存在寄存器的值。

使用特权

评论回复
沙发
updownq| | 2023-10-5 13:12 | 只看该作者
使用volatile关键字可以明确地告诉编译器,这些变量的值可能会被意外地改变,因此在读取这些变量的值时,需要确保变量的值是最新的。这样可以使代码更加清晰和易于理解。

使用特权

评论回复
板凳
lihuami| | 2023-10-5 13:27 | 只看该作者
单片机中的 volatile 关键字用于确保对变量的访问是稳定的,不会受到编译器的优化干扰

使用特权

评论回复
地板
cemaj| | 2023-10-5 13:52 | 只看该作者
volatile是一个关键字,用于告诉编译器该变量可能会在程序执行期间被意外修改,因此编译器不应该对该变量进行优化或假设其值不会改变。

使用特权

评论回复
5
kkzz| | 2023-10-5 15:09 | 只看该作者
防止编译器对其进行优化              

使用特权

评论回复
6
tabmone| | 2023-10-5 15:28 | 只看该作者
volatile关键字的作用是提高代码的可读性和可维护性,提高代码的执行效率,并通知编译器变量的值可能会被意外地改变。

使用特权

评论回复
7
abotomson| | 2023-10-5 17:22 | 只看该作者
volatile 告诉编译器,变量的值可能会在程序的控制之外被改变,因此每次访问这个变量时都必须从内存中读取,而不是使用寄存器中的值

使用特权

评论回复
8
uiint| | 2023-10-5 17:30 | 只看该作者
通过使用volatile关键字,可以避免不必要的内存访问和数据复制,从而提高程序的性能和效率。

使用特权

评论回复
9
uptown| | 2023-10-5 18:56 | 只看该作者
volatile关键字可以用于修饰变量,表示该变量可能会被意想不到地改变

使用特权

评论回复
10
eefas| | 2023-10-5 19:25 | 只看该作者
volatile关键字可以禁止指令重排。

使用特权

评论回复
11
vivilyly| | 2023-10-5 19:49 | 只看该作者
在使用volatile关键字时,需要注意变量的可见性和更新方式,并确保代码的正确性和可靠性。

使用特权

评论回复
12
tabmone| | 2023-10-5 20:07 | 只看该作者
通过使用volatile关键字,可以告诉编译器不要对该变量进行优化,而是始终从内存中读取或写入变量的值。

使用特权

评论回复
13
geraldbetty| | 2023-10-5 20:18 | 只看该作者
在一个循环中多次访问同一个volatile修饰的变量,可能会导致变量的值不断变化,从而导致死锁。通过使用volatile关键字,可以避免出现死锁问题。

使用特权

评论回复
14
maqianqu| | 2023-10-5 20:48 | 只看该作者
volatile 告诉编译器,变量的值可能会在程序的控制之外被改变,因此每次访问这个变量时都必须从内存中读取,而不是使用寄存器中的值

使用特权

评论回复
15
mollylawrence| | 2023-10-5 21:18 | 只看该作者
使用volatile关键字可以保证内存的可见性,即当本地内存。

使用特权

评论回复
16
jonas222| | 2023-10-5 21:48 | 只看该作者
volatile关键字的作用主要是确保变量的值不会因为编译器的优化而改变。这意味着,如果一个有volatile修饰的变量在被访问前发生了变化,那么编译器会对这个变量进行重新读取,而不是依赖于之前的读取结果。

使用特权

评论回复
17
ccook11| | 2023-10-5 22:18 | 只看该作者
volatile关键字是一个非常重要的关键字,用于控制变量的可见性和更新方式

使用特权

评论回复
18
sesefadou| | 2023-10-8 12:26 | 只看该作者
在单片机编程中,由于硬件的限制,一些变量的值可能会被意外地改变,例如中断、硬件状态变化等。使用volatile关键字可以避免编译器进行不必要的优化,例如缓存变量的值等。这样可以提高代码的执行效率。

使用特权

评论回复
19
hilahope| | 2023-10-8 12:37 | 只看该作者
当一个变量被声明为 volatile 时,编译器将不会对它进行任何优化,以确保变量的值不会被意外地被编译器优化掉。这对于一些特殊用途的变量非常重要

使用特权

评论回复
20
kmzuaz| | 2023-10-8 12:45 | 只看该作者
在单片机编程中,由于硬件的限制,一些变量的值可能会被意外地改变,例如中断、硬件状态变化等。使用volatile关键字可以明确地告诉编译器,这些变量的值可能会被意外地改变,因此在读取这些变量的值时,需要确保变量的值是最新的。这样可以使编译器更加谨慎地处理这些变量,以避免出现错误。

使用特权

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

本版积分规则

55

主题

1332

帖子

2

粉丝