(*(volatile unsigned int *)0x0000FFF0)
(*(volatile unsigned int *)0x0000FFF0)
在MCU的底层驱动中经常看到这样的对寄存器地址操作的C语言写法,下面来一一分析下这个
为了简化对该表达式的理解可以分两步走
对上面表达式进行简化如下:
(*(volatile unsigned int *)(x)) 注意这里将上面常量用一个变量替换是便于下面分析
再简化
p=(volatile unsigned int *)(x)
(*p)
再简化我们拿掉看不懂的volatile
1) p=( unsigned int *)(x)
2) (*p)
现在就很清楚了,第一个表达式将变量x转换为指针,该指针我们给它取名为p,原先x本来是存数据的,现在无非是拿来存地址了,就是这样。
第二个表达式就更简单了就是取该指针里的值
现在我们变换一下,将x变量换成常量,这里先给个值吧,比如就是标题的0x0000FFF0
还是一样分两步走
1) p=( unsigned int *)(0x0000FFF0)
2) (*p)
第一个表达式将常量转换为指针,第二个表达式就是取该指针所存取地址的值,现在问题来了那常数是不可以存地址的,所以很明显了这里常数就是该地址值,所以就可以概括了,就是0x0000FFF0地址的值
还有最后一个问题要解决了,就是这个类型转换前面的volatile
这个其实就是告诉编译器对该变量不要进行优化,每次都是从该地址读取数据,这样是为了防止一些错误。
还是举个例子来说好了
Int *a,int b;
b=(*a) *(*a);
单单看第二个表达式,可以知道需要在a所指向的地址连续取两次值,而计算机中一般取的值肯定是存在某一个存储空间上的,计算机在编译这段代码时会考虑到读取效率的问题,就会将读取两次值改为一次,怎么改呢,那就是先将a所指向的地址取一次值,然后保存起来,以后用到的话,就直接用保存起来的那个值就好了。
计算机优化后的代码可能长成这样:
Int *a,int b;
c= *a;
b=c*c;
但是若是在*a前面加了volatile情况就会像我们所想那样工作,而不会被编译器优化了,其实这个主要的好处还是为了减少错误,试着想一下,当将一个地址拿来的东西存到一个地方,万一那个地方出了问题,数据丢失了就糟糕了,当然这只是万一。
综合分析来看,为了提高代码执行效率,就不加volatile,有利于代码优化,提升计算机执行效率,但为了防止关键数据丢失或减少不确定性,就加volatile,减少错误发生。
最后要记住volatile:中文意思为易变的
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步