volatile 和 register关键字在嵌入式中基本用法

Refer: C 关键字之别搞砸了 volatile_c结构体可以加 volatile吗-CSDN博客

C keywords: Don't flame out over volatile - Embedded.com

ReC语言中volatile关键字的作用_volatile static一起用-CSDN博客

C语言关键字详解(五)带你全面了解 volatile 关键字_c语言_野猪佩奇`-开放原子开发者工作坊 (csdn.net)

一、volatile在嵌入式中的基本用法

1.用于内存IO映射
2.在多任务中用作全局共享数据
3.在中断里使用

1.1 概述

想必大家平时都见过volatile关键字“易变的”,可是大家知道什么时候需要使用volatile关键字吗?
直接看下面代码:

int a = 100;
while(a == 100)
{ 
    // code
}

这段程序编译时,如果编译器发现程序始终没有企图改变a的值,那它可能就会优化这段代码,变成while(true)的死循环使得程序执行的更快,然而这种优化有时候会变成过度优化,编译器有时候可能没有意识到程序会改变a的值,却做了这种优化导致程序没有产生预期的行为。
这里为了产生预期的行为,需要阻止编译器做这种优化,可以使用volatile关键字修饰。

volatile int a = 100;

volatile关键字和const关键字相对应:
const关键字告诉编译器其修饰的变量是只读的,编译器根据只读属性做一些操作;
而volatile关键字告诉编译器其修饰的变量是易变的,同理编译器根据易变属性也会做一些操作。它会确保修饰的变量每次都读操作都从内存里读取,每次写操作都将值写到内存里。volatile关键字就是给编译器做个提示,告诉编译器不要对修饰的变量做过度的优化,提示编译器该变量的值可能会以其它形式被改变。

volatile修饰结构体时,结构体的成员也是volatile的吗?

struct A 
{    
    int data;
};
volatile A a;
const    A b;

答案是结构体内所有的都是volatile,引用c++标准里的一句话:
[Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C + + as they are in C. ]
这里大体可以理解为一个对象是volatile,那对象里所有的成员也都是volatile。

其实const和volatile可以理解为是硬币的两面,我们经常听到看到传说中的CV修饰词就是const和volatile关键字。

volatile可以保证原子性吗?

想必大家都知道答案: volatile只保证内存可见性,不能保证操作是原子的,拿i++举例:

volatile int i = 0;
i++;                // i = i + 1

i++ 相当于i=i+1,而i=i+1其实可以分解为好几步:

先读取i的值到tmp
增加tmp的值
把tmp的值写回到i的地址里

而volatile只能保证内存可见,可以理解为上述三步中的每一步都是原子的,但是三步合起来却不一定是原子的,因为在多线程中三步中间可能插入一些其它操作改变了预期的行为,所以volatile不能用在多线程中,多线程中的原子操作还是需要使用atomic。单例模式的double check方法中instance变量为什么需要使用volatile修饰也是这个原理。

小总结
tips:volatile不能解决多线程安全问题,针对特种内存才需要使用volatile。
它和atomic的特点如下:• std::atomic用于多线程访问的数据,且不用互斥量,用于并发编程中•
volatile用于读写操作不可以被优化掉的内存,用于特种内存中
。参考资料https://stackoverflow.com/questions/4437527/why-do-we-use-volatile-keywordhttps://stackoverflow.com/questions/72552/why-does-volatile-existhttps://stackoverflow.com/questions/4479597/does-making-a-struct-volatile-make-all-its-members-volatile/4479652https://stackoverflow.com/questions/19744508/volatile-vs-atomichttps://blog.csdn.net/bdss58/article/details/44813597

二、 register关键字在嵌入式中的应用

Refer:C语言关键字详解(一) auto、register关键字_c语言auto和register-CSDN博客

register修饰变量的作用:尽量将所修饰变量,放入CPU寄存区中,从而达到提高效率的目的
register修饰变量提高效率的本质:将变量放入寄存器中,使CPU可以直接对该数据进行操作,而不需要从内存中对其进行读取。
既然用register修饰的变量可以提高效率,那么是不是所以的变量都最好用register修饰呢?答案当然不是的。因为寄存器的数量是有限的,大量使用register修饰反而会降低程序的运行效率。

那么什么样的变量应该被register修饰呢?

(1)局部的(全局会导致CPU寄存器被长时间占用)
(2)不会被写入的(对数据进行写入需要将数据重新加载进内存,这样也就失去了把数据放进寄存器当中的意义)
(3)需要被高频读取的(直接从寄存器中对该数据进行读取,提高效率)
注意:
(1)被register修饰的变量,不能取地址(因为该变量已经被放在寄存区中,而地址是内存相关的概念)
(2)register只是一个建议性的关键字,建议计算机将该变量放入内存之中,不是强制性的,也就是说,虽然一个变量已经被register修饰了,但是该变量还是可能被继续放在内存当中
(3)如果要使用register,请不要大量使用,因为寄存器数量有限

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值