volatile c语言_C语言“隐秘的角落”——Volatile

a6db3f737466bc4841d84376a1c72ad4.png

Tip 1 . Volatile 类型限定符

volatile : 英[ˈvɒlətaɪl] , adj, 易变的

vlatile限定符的意义是:通知编译器,程序中某些数据是“易变的”。

它通常使用在指向易变内存空间的指针声明中。

举一个在嵌入式中的实例:

87ad5d27a313729381e644f80ed8f19d.png

ac000ebc5bfd0be403714ee3e4e030c6.png

很显然我们看到这些地址是寄存器R0,R1,R2,R3,LC.. 的地址,当中断来时,我们将读取这些寄存器中的值存在缓冲区中。那么从上面来看,容易知道,我们是将这个地址先强制转化为volatile unsinged long的指针,然后对其内存地址取值。

因为在底层中,这几个寄存器的值是随时在改变的,所以在这里使用vlatile对其进行标识,来告诉编译器,这些数据是“易变”的,防止出现一些未知的错误。

可是为什么?又会有哪些错误呢?

再来看一个例子。

f655c01325baab358a008a2cd084d533.png

这里是使用键盘输入的缓冲区赋值,我们输入将存在p指向的这段内存中。

看起来,代码没有任何问题,当判断出这段字符串结束为‘\n’,那么结束while循环。

可是使用有些编译器会让整个结果出错,它会不停的复制同一个字符来填满缓冲区。

这是因为: 有一些编译器非常“聪明”,它发现在这段程序中,并没有对*p, 或者p有过改变,那么它可能只会对p做一次取值,而不是每次都重新去取值,这就导致它赋值缓冲区的值不变,可是实际上我们的input改变了很多次。

这时候,volatile就派上了用场。

c83ce3b14e72271d476390a5623b98c8.png

编译器瞅了一眼,哦,是volatile类型的数据,又得多跑几次了。

于是它就会按部就班的每次都去重新读取数据。

回到上面的实战案例,我们知道r0-pc这些寄存器的值都是易变的,那么,显而易见为了防止那些“聪明”的编译器,于是也加入了volatile限定符。

思考: volatile这个例子,就是编译器反作用于C代码的编写,大部分场景下,我们都可以不用这个限定符,可是在输入,中断,嵌入式底层中却常常需要去加入这个小家伙。 理论上,编译器是为了服务于C语言而存在的,可它却改变了C语言代码本身的编写,增加了相互的耦合,如果可以的话,当然我们想要编写代码更轻松,麻烦的工作都交给自动化的程序,可是有些场合是很难通过编译器来识别的,那么只能麻烦程序员在写代码更加的严谨。 辩证的来看,世界上没有什么事情都独立存在的,所有妄想完全独立自主的生活下去都会受到世界的严惩,有时候为了自由可能会付出的更多,可还是会有人愿意这么做,很难去说明是谁对谁错,那么就依照自己的本心去做好了。

3fccc2b7d43ae87be2f7f2a0ffdd00c4.png

点赞+关注哦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值