关于c中volatile关键字(转贴)

C语言中volatile关键字用法 1.1. 编译器的优化介绍 介绍Volatile关键字之前我们先了解一下编译器的优化。 高速缓存:处理器读取程序里面的数据时,把一些访问频率比较高的数据,临时存储到寄存器(register)中,当需要取数据时,就会从 register 中取,而不是直接去从 memory(内存)中取,节约了时间,像这样的过程,叫做高速缓存。 硬件级别的优化:内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存(Cache),加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执 阅读详情
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
    1). 并行设备的硬件寄存器(如:状态寄存器)
    2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
    3). 多线程应用中被几个任务共享的变量
    回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
    假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得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可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
     long square(volatile int *ptr)
     {
            int a;
            a = *ptr;
            return a * a;
     }
     
    
    
Volatile 关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,以避免在其中一个线程操作该变量时,将其拷贝入寄存器。请看以下情形:

   A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足一定条件(它期待B线程改变变量的值。
在此种情况下,当B线程改变了变量的值时,已改变的值对其在寄存器的值没有影响。所以A线程进入死循环。
  
   volatile 就是在此种情况下使用。

 


What does volatile do?


This is probably best explained by comparing the effects that volatile and synchronized have on a method. volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

         int i1;              int geti1() {return i1;}
volatile int i2; int geti2() {return i2;}
int i3; synchronized int geti3() {return i3;}

geti1() accesses the value currently stored in i1 in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated i1in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.


On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that volatile variables have a higher access and update overhead than "plain" variables, since the reason threads can have their own copy of data is for better efficiency.


Well if volatile already synchronizes data across threads, what is synchronized for? Well there are two differences. Firstlysynchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:



  1. The thread acquires the lock on the monitor for object this (assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked). 
  2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory (JVMs can use dirty sets to optimize this so that only "dirty" variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification). 
  3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from "main" memory). 
  4. (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.) 
  5. The thread releases the lock on the monitor for object this.

So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

C语言关键字之“volatile” 个人学习过程中对"volatile"关键字的一些见解! 阅读详情

相关推荐

PINN内嵌物理知识神经网络入门及文献总结

内嵌物理知识深度学习方法(PINN)已经成功用于解决各类科学计算问题,其本质是将物理先验知识嵌入神经网络训练中,将一个求解PDE的问题转化为一个优化问题。这篇博客主要记录PINN相关论文

山里娃的博客 7万+

C语言中volatile关键字的作用

volatile 的作用 是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。 如上代码,如果选择编译器优化,可能会被编译成如下代码(当然不是在C语言层面上优化,而是在汇编过程优化,只是使用C程序举例): 因为在仅仅从main主函数来看,a == b是必然的,那么在什么情况,a 和 b不是必然相等呢?volatile 常见的几个面试题:1、一个参数既可以是const还可以是volatile吗?可以,例如只读的状态寄存器。它是 volatile 因为它可能被意想不到地改变。它是 con

打不倒的程序猿 1万+

AIR780E二次开发点灯(LuatOS)

Air780E的LuatOS点灯教程,二次开发教程,可用于所有ec618平台,无需SDK

rootuseres的博客 1万+

c语言中volatile关键字

使用volatile的变量必须满足以下条件之一:被硬件/中断修改被多线程共享且无锁保护被信号处理函数修改场景编译器优化风险volatile的作用硬件寄存器访问缓存导致读取旧值强制每次从内存地址读取最新值中断服务程序变量被中断修改但未被察觉确保主程序读取修改后的值多线程共享变量指令重排导致状态不一致禁止重排(需结合锁或原子操作)内存映射I/O冗余操作被优化导致逻辑错误保留所有读/写操作。

shuigege1111的博客 4450

ML307A模组通过MQTT协议接入OneNET平台的AT指令全解析

本文详细解析了ML307A模组通过MQTT协议接入OneNET平台的完整AT指令流程。从平台侧的产品创建、设备添加,到核心难点连接密钥的计算方法,再到模组侧的基础网络附着、MQTT连接配置、数据收发及调试排错,提供了手把手的实战指南,帮助开发者快速实现物联网设备上云。

weixin_29240711的博客 494

喷涂机器人系列编程:ABB IRB 5500_(9).常见故障诊断与排除

ABB IRB 5500 喷涂机器人在实际应用中可能会遇到各种故障,但通过系统的诊断和排除方法,可以确保生产线的连续运行。定期维护和保养是预防故障的重要手段,而操作培训和规范则能有效减少人为因素引起的故障。希望本节内容能帮助操作和维护人员提高故障诊断和排除的效率,确保喷涂机器人的稳定运行。如果您有任何疑问或需要进一步的帮助,请联系 ABB 客户服务中心。

zhubeibei168的博客 1045

【C语言】关键字volatile的作用是什么

`volatile`是一个C/C++关键字,它用于告诉编译器当前变量是易变的,需要在每次使用时都从内存中重新获取值,而不是使用缓存中的旧值。

Goforyouqp的博客 1万+

【数据结构】考点二十八 : 二叉树的概念:二叉树的度、完全二叉树、满二叉数结点数、哈夫曼结点数、完全二叉树的深度

二叉树(Binary Tree)是一种常见的数据结构,它或者为空(null),或者由一个根节点(root node)和两个子树(left subtree 和 right subtree)组成,这两个子树又分别是一棵二叉树。二叉树的每个节点最多有两个子节点,通常称为左子节点(left child)和右子节点(right child)。

超越的博客 1738

嵌入式C语言中的关键字volatile

由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进行优化。编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。

千月星跡 1867

(第14天)Veritas NetBackup(NBU) 配合 RMAN 脚本备份 Oracle 数据库

NBU(Veritas Netbackup)是企业中比较常用的备份软件,通常用于备份企业使用中的系统,数据库,文件等等,通常是搭配 Oracle RMAN 来进行备份 Oracle 数据库。

LuciferLiu_DBA 1642

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的生活垃圾检测与分类系统(Python+PySide6界面+训练代码)

随着城市化进程的加速和人口增长,生活垃圾管理已成为现代城市面临的重要挑战。传统的垃圾处理方法效率低下且成本高昂,急需智能化解决方案。本文详细介绍了基于YOLO系列算法(特别是YOLOv8)的智能生活垃圾检测与分类系统,该系统能够实时识别和分类多种生活垃圾,为智能垃圾处理和回收提供技术支持。系统包含完整的数据集构建、模型训练、评估和可视化界面,并提供了完整的实现代码。

YOLO 117

C语言再学习 -- 关键字volatile_c语言关键字 volatile delay

以上是硬件级别的优化。**对常规内存进行优化的时候,这些优化是透明的,而且效率很好。volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中。等待上面的线程终止,如果bStop不使用volatile申明,那么这个循环将是一个死循环,因为bStop已经读取到了寄存器中,寄存器中bStop的值永远不会变成FALSE,加上volatile,程序在执行时,每次均从内存中读出bStop的值,就不会死循环了。

2401_87555637的博客 1111

学习STM32的ADC采集声音

为了采集声音信号,需要一个声音传感器(如麦克风),将声音信号转换为电压信号输入到 ADC 引脚。通过硬件准备、STM32CubeMX 配置和代码实现,我们可以实现将声音信号转换为数字信号,并进行后续处理。STM32 是一款广泛应用于嵌入式系统开发的微控制器平台,其拥有丰富的外设和强大的性能,非常适合进行 ADC(模拟数字转换)的声音采集。函数启动 ADC1 的连续转换模式,然后在一个无限循环中等待 ADC 转换完成,并读取采样结果。四、代码实现 在生成的代码中,会生成一些相关的库文件和示例代码。

m0_75244442的博客 2174

C 易失性关键字volatile

C的volatile关键字是一个限定符,在声明变量时将其应用于该变量。它告诉编译器变量的值可以随时更改-编译器在附近找到的代码不会采取任何操作。这意味着非常严重的。但是,在检查它们之前,让我们看一下语法。 C的易失关键字的语法 要声明变量volatile,请在变量定义的数据类型之前或之后包含关键字volatile。例如,这两个声明都将一个无符号的16位整数变量声明为易失性整数: volatile uint16_t x; uint16_t volatile y; 现在,事实证明,指向易失性变量的指针非常普遍,

xiaogu0322的博客 1906

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

如何使用C的volatile关键字

首先声明本文译自国外网站的一篇文章,原文链接如下: https://barrgroup.com/embedded-systems/how-to/c-volatile-keyword 建议有条件的直接阅读英文原版。可能读了这篇文章后,你会有所怀疑,因为你平时可能遇到过下面出现的情况,但是你并没有添加volatile关键字,程序任然正常的运行,个人觉得可能有以下的原因: 1.其实BUG出现了,但是难以复现,所以被你忽略了 2.现在的优化器足够智能,即使打开了优化,也能避免这些BUG的出现

漫长当下 1615

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

C 语言常用关键字详解:static、const、volatile

在 C 语言中,staticconst和volatilestatic用于控制变量或函数的作用域和生命周期,确保它们不会被意外修改或访问。const用于修饰变量、指针或函数参数,表示它们的值在程序运行期间不可修改。volatile用于防止编译器优化,确保每次访问变量时都读取最新的值,尤其在硬件编程或多线程环境中非常有用。掌握这些关键字的使用方法,将有助于编写更高效、稳定和易于维护的 C 语言代码。

嵌入式修炼师的博客 1501

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

详解C中volatile关键字

详解C中volatile关键字 volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。在DSP开发中,经常需要等待某个事件的...

diruan7614的博客 412

C/C++ volatile 关键字的作用

防止编译器优化 在 C/C++ 中,编译器会对代码进行优化。例如,当一个变量在一个循环中被频繁读取,并且编译器认为这个变量的值不会在循环过程中改变时,它可能会把这个变量的值缓存起来,而不是每次都从内存中读取。但是对于一些特殊的变量,如硬件寄存器或者被多个线程或中断服务程序访问的共享变量,这种优化是不允许的。 例如,考虑一个简单的程序,它从一个硬件设备的寄存器中读取数据: 在这个例子中,关键字告诉编译器,的值可能会在程序不知情的情况下被改变(比如硬件设备更新了寄存器的值),所以编译器每次访问这个变量

2301_77891039的博客 592

C语言:volatile关键字讲解

易变”是因为外在因素引起的,像多线程,中断等。中修改的供其它程序检测的变量,需要加volatile:当变量在触发某中断程序中修改,而编译器判断主函数里面没有修改该变量,因此可能只执行一次从内存到某寄存器的读操作,而后每次只会从该寄存器中读取变量副本,使得中断程序的操作被短路。volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,告诉编译器对该变量不做优化,都会直接从变量内存地址中读取数据,从而可以提供对特殊地址的稳定访问。

_ 1622

C语言volatile关键字

1. 具体含义 Volatile关键字在C Language Keywords中的解释 Indicates that a variable can be changed by a background routine. Keyword volatile is an extreme opposite of const.It indicates that a variable may be changed in a way which is absolutely unpredictable by analysi

weixin_37515325的博客 415

C语言——volatile关键字讲解

许多程序员都无法正确理解C语言关键字volatile,这并不奇怪。因为大多数C语言书籍通常都是一两句一带而过,本文将告诉你如何正确使用它。 在C/C++嵌入式代码中,你是否经历过以下情况: 代码执行正常–直到你打开了编译器优化 代码执行正常–直到打开了中断 古怪的硬件驱动 RTOS的任务独立运行正常–直到生成了其他任务 如果你的回答是“yes”,很有可能你没有使用C语言关键字volatile。你并不是唯一的,很多程序员都不能正确使用volatile。不幸的是,大多数c语言书籍对volatile的藐视,只是

落子无悔的博客 4246

C 语言中的 volatile 关键字

在程序运行时,编译器通常会假设变量的值仅由当前线程或函数内的代码修改,并据此进行优化(如循环内变量提升、指令重排等)。此时,若未使用 volatile 修饰,编译器可能生成错误的优化代码,导致程序行为异常。volatile 是 C/C++ 语言中的一个类型修饰符,用于告知编译器:该变量的值可能会在程序控制流之外被意外修改(如硬件寄存器、多线程共享变量或信号处理函数等),因此编译器不应对其进行激进的优化(如缓存到寄存器或消除冗余读取)。测试,因为 ARM 是弱内存模型,更容易复现问题。

日常学习记录 969

C语言关键字之 volatile

C语言中 volatile 关键字的作用

Caso_卡索的博客 506

详解C语言中volatile关键字

volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如 果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举 例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序: short flag; v

脚踏实地,仰望星空 1万+

C语言——volatile 关键字

这个专栏会专门讲一些C语言的知识,后续会慢慢更新,欢迎关注C语言专栏。

2201_75757246的博客 793
上一篇: c语言模拟实现栈的模板化
下一篇: Linux 进程栈和线程栈的区别
wong_daniel
博客等级 码龄19年 37粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值