• C语言学习及应用笔记之四:C语言volatile关键字及其使用


      在C语言中,还有一个并不经常使用但却非常有用的关键字volatile。那么使用volatile关键字究竟能干什么呢?接下来我将就此问题进行讨论。

      一个使用volatile关键字定义变量,其实就是告诉编译系统这变量可能会被意想不到地改变。那么编译时,编译器就不会自作主张的去假设这个变量的值,而进行代码的优化了。确切的说就是,编译器在编译代码时,优化器每次遇到这个变量,都会到内存中重新读取,而不会使用保存在寄存器里的备份来对代码进行优化。

      我们已经了解了volatile关键字的基本作用。那么,在什么情况下使用volatile关键字呢?一般说来,在如下的几种情况通常会使用volatile关键字:

    • 在中断服务程序中修改的,供其它程序检测的变量,通常需要定义为volatile;
    • 在多任务环境下,各任务间共享的标志,通常也需要定义为volatile;
    • 存储器映射的硬件寄存器通常也需要定义为volatile,因为每次对它的读写都可能有不同意义;

    1)使用中断改变对象值的情况

      我们在中断服务程序中操作了某个对象,比如谁改变了一个变量的值。而在其它程序中我们希望通过这个变量值得改变去进行一些操作。在这个时候,我们使用或者不使用volatile关键字,可能得到截然不同的结果。

      如果我们将变量定义为:static int var=0; ,然后再中断服务成勋中将其修改为:var=1,但是在另一函数中使用它但不会修改它,那么编译器会认为它没有变化,从而直接使用寄存器中的副本。

      如果我们将变量定义为:volatile int var=0;,那么结果就完全不同了,每次在函数中使用var变量时,都会重新读取,而不会使用寄存器中的副本。

    (2)多任务共享标志的情况

      多任务共享时,其实也是一样的,在一个任务中修改了一个对象后,在另一个对象中应用它,但编译器并没发现在该任务中对它有修改。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。从而并不能响应在另一任务下的变化。

      在这种情况下,一般我们都需要使用volatile关键字来定义任务间共享的标识。

    3)硬件寄存器内存映射的情况

      内存映射的情况是非常多的,比如我们将外设的寄存器映射到内存的某一段区域;再比如我们同过DMA方式将数据直接写到内存中的某一段区域。

    由于我们外部的数据都是直接进入了内存区域,而程序知识引用它的值。编译器优化时可能就直接采用寄存器中的副本了。佷显然这不是我们需要的结果,这时将这段内存对应的变量声明为volatile,则可以保证我们的需求。

      综上所述,我们说明了volatile关键字的常规用法。当然,我们也可以发现volatile关键字是会降低编译器优化力度的,但它却可以保证程序的正确性,所以在适合的地方使用volatile关键字是必要的。不过能不能用的好,还要看编程者的基本功。

    欢迎关注:

  • 相关阅读:
    poj 1789 Truck History(最小生成树)
    POJ 3096 Surprising Strings(STL map string set vector)
    hdu 1412 (STL list)
    POJ 1552 Doubles (C++ STL set使用)
    poj 水题系列
    洛谷P4859 已经没有什么好害怕的了
    CF1228E Another Filling the Grid
    二项式反演
    AT [ABC177F] I hate Shortest Path Problem
    [NOI2020]制作菜品
  • 原文地址:https://www.cnblogs.com/foxclever/p/9906132.html
Copyright © 2020-2023  润新知