【问题标题】:the volatile keyword in C language? [duplicate]C语言中的volatile关键字? [复制]
【发布时间】:2011-04-28 17:07:34
【问题描述】:

我有一个关于 C 语言中 volatile 的问题。

我阅读了一些教程但仍然无法弄清楚,有人说 volatile 告诉编译器优化器涉及此变量的操作不应该以某些方式进行优化。 这意味着只要变量的值在寄存器中发生变化,那么该值就会影响内存。

也有人说 volatile 意味着可以通过此代码之外的方式更改值。

第二个说法我看不懂,所以可以通过这段代码之外的方式改变 volatile 变量?如何?这两个说的都对吗?

【问题讨论】:

    标签: c volatile


    【解决方案1】:

    “可以通过此代码之外的方式更改值”的声明基本上意味着另一个程序或硬件可以更新该变量。这是完全可能的。一种思考方式是将此概念与在多个程序之间共享的文件相关联。一个文件可以同时被多个程序打开、写入和读取。当您从文件中读取时,您要确保您正在阅读最新的更新,而不是最旧的。

    回到 volatile 关键字,将 volatile 放在变量之前,实际上是做同样的事情。它确保您从变量中读取的内容不是基于编译器的优化或程序拥有的变量的旧副本。此外, volatile 关键字确保每次访问时都从内存中获取变量。因此,关于 volatile 关键字,这两种说法都是正确的。

    【讨论】:

    • 我不明白一个硬件如何改变变量?这是否意味着硬件不需要某些方法或代码来修改变量?
    • @ratzip:是的。变量是内存中包含一个值的位置,而内存只是一个硬件(例如 RAM 芯片)。许多计算机系统(键盘、网络、音频输入等)都设置为外部硬件可以直接修改某些内存位置。
    【解决方案2】:

    C 不一定适用于计算机。例如,如果您正在为 Game Boy Advance 进行开发,您经常会遇到由硬件修改的内存位置,因此 您可能不会修改代码中的变量,但无论如何它都会被修改.这就是volatile 的意思。

    通过添加volatile 关键字,您是在告诉编译器“存储在此变量(内存位置)中的值可能会在我的代码不做任何事情的情况下发生变化。” em>

    【讨论】:

    • 为什么这是 C 标准的这一部分而不是这些实现的扩展 - 没有一致的方法来获取指向以这种方式运行的内存的地址。
    • @Random:因为它就是这样。无论如何,几乎每个平台都需要在某个时候与硬件进行交互。
    • 在某些嵌入式平台上 - 与 GBA 一样,您有内存映射寄存器,因此您知道内存中的某个区域以这种方式运行。跨度>
    • @Random:你能解释一下吗?您认为不可能指示连接的设备使用特定的内存位置作为它们的缓冲区或在哪里传输接收到的信号?
    • @Random:C 标准也没有定义应该如何解析#includes。这并不意味着它们没有用。
    【解决方案3】:

    考虑以下任何一项:

    • 多线程应用程序,
    • 使用共享内存的应用程序,
    • 在将 I/O 寄存器映射到地址空间的平台上运行的应用程序,
    • 在后台发生硬件 DMA 的应用程序。

    在每种情况下,都可以在当前线程之外更改内存。

    注意“只要变量的值在寄存器中发生变化,那么该值就会影响内存”是正确的,只是不是很清楚。

    【讨论】:

    • 而且这两种说法都对吗?
    • 但是volatile 对多线程代码非常非常有用。
    • volatile 在数据可以被异步事件修改的情况下也很有用,例如信号处理程序代码的执行(即信号处理程序代码修改了变量)。
    • C 规范中没有要求 volatile 具有获取/释放语义或任何其他对多线程代码实际有用的语义。请记住,不同的线程可能会针对不同处理器上的不一致缓存进行操作;不要求编译器实现 volatile 来考虑这一点。除非您正在为特定编译器编写代码并且您知道编译器针对 volatile 实现了 C 语言的哪些扩展,否则您不应该将 volatile 用于线程语义。
    • @EricLippert:C 标准中也没有要求一致的实现适用于任何目的。标准不要求符合标准的实现做某事这一事实并不意味着旨在适合低级编程的高质量实现不应该这样做。不幸的是,编译器将实现质量问题视为实现劣质语义的借口是一种时尚。
    【解决方案4】:

    可以通过多种方式在程序代码之外更改内存位置。例如,从磁盘读取的 DMA 可以写入缓冲区,或者内存映射设备可以因为设备上的某些事件而更改位置。

    【讨论】:

      【解决方案5】:

      这适用于多线程应用程序:变量的值可以由多个线程更改,因此必须在每次访问时与内存“同步”(无论是读取还是写入值) .

      【讨论】:

      • volatile 对于多线程代码非常非常有用。
      【解决方案6】:

      声明一个 volatile 变量意味着,您是在指示编译器不要围绕该变量优化代码 sn-p。这是为了强制 cpu 不使用本地寄存器或缓存内存中的变量值,而是每次都从主内存中获取值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-08
        • 1970-01-01
        • 1970-01-01
        • 2015-06-03
        • 2011-04-05
        相关资源
        最近更新 更多