C++中的volatile

这篇具有很好参考价值的文章主要介绍了C++中的volatile。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

volatile的本意是“易变的”,是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

当要求使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被寄存。例如:

volatile int i=10;
 
int a = i;
 
。。。//其他代码,并未明确告诉编译器,对i进行过操作
 
int b = i;

volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问

#include <iostream>
using namespace std;

int main(int argc,char* argv[])
{
    int i=10;
    int a=i;
    cout<<a<<endl;
    _asm
    {
        mov dword ptr [ebp-4],80
    }
    int b=i;
    cout<<b<<endl;
}

程序在VS2012环境下生成Release版本,输出结果是:
10
10

阅读以上程序,注意以下几个要点:

以上代码必须在Release模式下考查,因为只有Release模式下才会对程序代码进行优化,而这种优化在变量共享的环境下容易引发问题。
在语句b=i;之前,已经通过内联汇编代码修改了i的值,但是i的变化却没有反映到b中,如果i是一个被多个任务共享的变量,这种优化带来的错误很可能是致命的。
汇编代码[ebp-4]表示变量i的存储单元,因为ebp是扩展基址指针寄存器,存放函数所属栈的栈底地址,先入栈,占用4个字节。随着函数内申明的局部变量的增多,esp(栈顶指针寄存器)就会相应的减小,因为栈的生长方向由高地址向低地址生长。i为第一个变量,栈空间已被ebp入栈占用了4个字节,所以i的地址为ebp-i,[ebp-i]则表示变量i的存储单元。

加上volatile关键字

#include <stdio.h>
 
void main()
 
{
 
volatile int i=10;
 
int a = i;
 
 
 
printf("i= %d/n",a);
 
__asm {
 
 mov dword ptr [ebp-4], 20h
 
}
 
 
 
int b = i;
 
printf("i= %d/n",b);
 
}

在调试版本和release版本运行程序,输出都是:

i = 10

i = 32

 这说明这个volatile关键字发挥了它的作用!

总结:建议编译器不要对该变量进行优化

扩展问题:

1). 一个参数既可以是const还可以是volatile吗?解释为什么。

2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:        
 

    int square(volatile int *ptr)
     
             {
     
                  return *ptr * *ptr;
     
             }

   

1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3). 这段代码的有个恶作剧。这段代码的目的是用来返指针ptr指向值的平方,但是,由于ptr指向一个volatile型参数,编译器将产生类似下面的代码:


     int square(volatile int *ptr)
     
        {
     
             int a,b;
     
             a = *ptr;
     
            b = *ptr;
     
             return a * b;
     
         }

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:文章来源地址https://www.toymoban.com/news/detail-696659.html

     long square(volatile int *ptr)
     
         {
     
                int a;
     
                a = *ptr;
     
                return a * a;
     
         }
         ```

到了这里,关于C++中的volatile的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • volatile - (C语言)

    volatile和const一样都是一种类型修饰符,用它修饰过的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者是其它线程等。 该是不希望被编译器优化,从而达到稳定访问内存的目的。 示例代码:  在程序运行起来后,查看反汇编(两个版本):

    2024年02月08日
    浏览(37)
  • C语言volatile关键字

    在C语言中, volatile 是一个类型修饰符,用于告诉编译器对象的值可能会在编译器无法检测到的情况下被改变。这通常发生在以下两种情况: 硬件的输入/输出操作,例如一个设备寄存器的读取或写入。 共享内存的并行程序,其中一个线程修改了一个内存位置,而另一个线程

    2024年02月07日
    浏览(51)
  • c++ 学习 之 const,constexpr,volatile

    const、constexpr 和 volatile 是 C++ 中用于修饰变量和类型的 它们分别用于不同的用途: const(常量): const 用于声明常量,表示变量的值不能被修改。 它可以应用于变量、指针、引用、成员函数以及类对象。 常量变量必须在声明时初始化。 常量成员函数承诺不修改对象

    2024年02月09日
    浏览(47)
  • Java中的volatile关键字实现原理

    在并发编程中,线程之间的可见性问题是非常重要的一项难题。Java中提供了一种解决并发可见性问题的机制,即volatile。 在本文中,我们将会讲解Java中volatile的实现原理,为什么它能够保证可见性,以及背后的实现原理涉及到的内存屏障和JVM屏障等内容。在学习

    2023年04月27日
    浏览(41)
  • STM32编程中的volatile,const意义

    __I、 __O 、__IO是什么意思? 这是ST库里面的宏定义,定义如下: #define __I volatile const /*! defines \\\'read only\\\' permissions */ #define __O volatile /*! defines ‘write only’ permissions / #define __IO volatile /! defines ‘read / write’ permissions */ 显然,这三个宏定义都是用来替换成 volatile 和 const 的,所以

    2024年02月15日
    浏览(52)
  • C++中volatile的具体含义和可能得坑

      似乎很多人不理解voliate和atomic啥区别,本文主要主要描述volatile的作用和使用场景。对比了atomic和volatile的区别,以及性能差异。最后补充了几条可能导致C++代码测试volatile导致正确结果错误结论的依据。   Every access (read or write operation, member function call, etc.) made through

    2024年01月22日
    浏览(46)
  • Java面试题:请谈谈Java中的volatile关键字?

    在Java中,volatile是一种特殊的修饰符,用于确保多线程环境下的变量 可见性和顺序性 。当一个变量被声明为volatile时,它可以确保以下两点: 内存可见性 :当一个线程修改了一个volatile变量的值,其他线程会立即看到这个改变。这是因为volatile会禁止CPU缓存和编

    2024年04月23日
    浏览(53)
  • 关于c++中mutable、const、volatile这三个关键字及对应c++与汇编示例源码

    这哥三之间的关系是有趣的,不妨看看这个: cv (const and volatile) type qualifiers - cppreference.com permits modification of the class member declared mutable even if the containing object is declared const. 即便一个对象是const的,它内部的成员变量如果被mutable修饰,则此成员变量依旧可以被修改。 很常见,

    2024年02月13日
    浏览(37)
  • C语言与C++语言中的memset函数

    memset 是一个 C 语言库函数,它位于 string.h 头文件中。这个函数的主要作用是将一块内存区域的内容全部设置为指定的值。 memset 的原型如下: 参数说明: void *s:指向要设置的内存区域的指针。 int c:要设置的值,虽然是 int 类型,但实际上只使用了它的低 8 位(一个字节)

    2024年02月10日
    浏览(36)
  • C语言中volatile/register/const/static/extern/auto关键字的作用

    目录 一、volatile 二、register详解 三、const详解 四、static详解 五、extern详解 语法 作用 六、auto详解 突然想总结一下这些的作用,灵活使用这些对程序的可靠性和速率都有提高 volatile是防止编译器优化,如果是高频繁的变量编译器会自动将变量放到寄存器中,但是有的变

    2024年02月07日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包