揭秘volatile在单片机编程中的作用:为何你的变量总被编译器“优化”掉?

C语言volatile关键字在单片机中的作用 volatile的本意是“易失的,易改变的”。在C语言中,这个限定词的含义是向编译器指明变量的内容可能会由于其它程序的修改而变化。 通常,在程序中申明了一个变量时,编译器会尽量把它放在通用寄存器中,例如ebx。当CPU把其值放到ebx中后就不会再关心对应内存中的值。若此时其它程序(例如内核程序或一个中断)修改了内存中它的值, ebx中的值并不会随之更新。为了解决这种情况就创建了volatile限定... 阅读详情

第一章:揭秘volatile在单片机编程中的作用:为何你的变量总被编译器“优化”掉?

在嵌入式开发中,尤其是使用C语言进行单片机编程时,你是否遇到过这样的情况:一个变量在中断服务程序中被修改,但在主循环中却始终无法读取到最新值?这往往不是硬件问题,而是编译器“过度优化”的结果。

编译器优化带来的陷阱

现代C编译器为了提升执行效率,会对代码进行各种优化。例如,如果编译器发现某个变量在函数内部未被显式修改,它可能直接从寄存器中读取缓存值,而不是重新访问内存。然而,在单片机环境中,变量可能被外设、DMA或中断服务程序异步修改,这种优化就会导致逻辑错误。

volatile关键字的正确使用

volatile关键字告诉编译器:“这个变量可能在任何时候被外部因素修改,请每次访问都从内存读取。” 它禁止编译器对该变量进行缓存优化。 以下是一个典型的应用场景:

// 共享变量,由中断修改
volatile uint8_t flag = 0;

void EXTI_IRQHandler(void) {
    if (EXTI_GetITStatus()) {
        flag = 1;  // 中断中修改
        EXTI_ClearITPendingBit();
    }
}

int main(void) {
    while (1) {
        if (flag) {           // 必须每次都从内存读取
            do_something();
            flag = 0;
        }
    }
}
若不加 volatile,编译器可能将 flag 缓存在寄存器中,导致主循环永远无法感知中断中的修改。

何时使用volatile?

  • 被中断服务程序访问的全局变量
  • 与硬件寄存器映射的内存地址
  • 多线程或多任务环境中共享的变量(如RTOS)
  • 通过指针传递且可能被外部修改的参数
场景是否需要volatile
普通局部变量否
中断中修改的全局标志是
映射到硬件寄存器的指针是

第二章:深入理解volatile关键字的语义与机制

2.1 volatile的基本定义与内存可见性保障

volatile 是 Java 中的一个关键字,用于修饰变量,确保其在多线程环境下的内存可见性。当一个变量被声明为 volatile,JVM 会保证对该变量的读写操作直接发生在主内存中,而非线程本地缓存。

数据同步机制
  • 每次读取 volatile 变量时,都会从主内存刷新最新值;
  • 每次写入 volatile 变量后,会立即写回主内存;
  • 禁止指令重排序,保障操作的有序性。
代码示例
public class VolatileExample {
    private volatile boolean running = true;

    public void stop() {
        running = false; // 主内存更新
    }

    public void run() {
        while (running) {
            // 执行任务
        }
        // 循环结束,因 running 从主内存读取
    }
}

上述代码中,running 被声明为 volatile,确保一个线程调用 stop() 后,另一个线程能立即感知到状态变化,避免无限循环。

2.2 编译器优化如何影响变量访问行为

编译器在提升程序性能时,常对变量访问进行重排序、缓存或消除冗余读写。这些优化虽提升效率,但也可能改变程序的预期行为。
常见优化类型
  • 常量折叠:在编译期计算表达式值
  • 死代码消除:移除看似无用的变量赋值
  • 寄存器缓存:将变量缓存在寄存器中,绕过内存同步
实例分析

int flag = 0;
void set_flag() {
    flag = 1;
    // 编译器可能省略对flag的写入,若后续无直接使用
}
上述代码中,若编译器判定flag的更新不影响局部逻辑,可能直接优化掉写操作,导致多线程环境下其他线程无法感知变更。
内存可见性保障
场景推荐机制
多线程共享变量volatile 或原子操作
硬件寄存器访问volatile 防止缓存

2.3 volatile与普通变量的汇编代码对比分析

在多线程编程中,`volatile`关键字用于确保变量的可见性,避免编译器过度优化。通过对比其与普通变量生成的汇编代码,可以深入理解底层机制差异。
测试代码示例

// 普通变量
int normal_var = 0;
void normal_write() {
    normal_var = 1;
}

// volatile变量
volatile int volatile_var = 0;
void volatile_write() {
    volatile_var = 1;
}
上述C代码在GCC编译后,两者生成的汇编指令存在显著差异。
汇编输出对比
场景关键汇编指令
普通变量写入可能被优化掉或缓存于寄存器
volatile变量写入强制写入内存,插入mfence等内存屏障
`volatile`修饰的变量每次访问都会从内存加载,禁止编译器将其缓存到寄存器,从而保证跨线程的最新值可见。

2.4 volatile在中断服务程序中的典型应用场景

在嵌入式系统开发中,中断服务程序(ISR)与主程序之间的数据共享常面临编译器优化带来的风险。`volatile`关键字在此类场景中起到关键作用,确保变量的读写操作不会被编译器优化或缓存到寄存器中。
数据同步机制
当主循环与中断服务程序共享状态标志时,必须使用`volatile`修饰该变量。例如:

volatile uint8_t flag = 0;

void ISR() {
    flag = 1;  // 中断中修改
}

int main() {
    while (1) {
        if (flag) {           // 主循环中检测
            handle_event();
            flag = 0;
        }
    }
}
上述代码中,若`flag`未声明为`volatile`,编译器可能将其优化为寄存器缓存值,导致主循环无法感知中断中的修改。加入`volatile`后,每次访问均从内存读取,保证了跨执行上下文的数据一致性。
  • 中断可能随时改变变量值
  • 主程序需实时感知最新状态
  • 编译器优化可能导致数据陈旧

2.5 实战:通过示波器验证volatile对执行时序的影响

在多线程环境中,volatile关键字常用于确保变量的可见性。为直观验证其对执行时序的影响,可结合硬件示波器观测程序运行的时间序列。
实验设计
使用两个线程分别读写共享变量:
  • 线程A循环读取volatile变量
  • 线程B周期性修改该变量
通过GPIO引脚输出电平信号标记关键操作点,接入示波器捕获时序。
代码实现

volatile boolean flag = false;

// 线程A:监听变化
new Thread(() -> {
    while (!flag) {
        // 空转
    }
    setPinHigh();  // 拉高电平,示波器可观测到上升沿
}).start();

// 线程B:触发修改
new Thread(() -> {
    flag = true;
}).start();
上述代码中,volatile保证了flag的修改对线程A立即可见。若未声明为volatile,线程A可能因缓存未更新而长时间无法感知变化,示波器将显示更长的延迟。
观测结果对比
变量类型平均响应延迟
普通变量约 300μs
volatile变量约 50μs
实验表明,volatile显著缩短了状态传播延迟,体现了其在内存屏障和缓存同步中的作用。

第三章:嵌入式系统中volatile的经典使用场景

3.1 处理外设寄存器映射时的volatile必要性

在嵌入式系统中,外设寄存器通常被映射到特定的内存地址。编译器可能对重复访问同一地址的代码进行优化,误认为其值不变,从而引发数据不一致问题。
volatile关键字的作用
使用 volatile 可告知编译器该变量可能被外部硬件修改,禁止缓存到寄存器或优化读写操作。

#define UART_STATUS_REG (*(volatile uint32_t*)0x4000A000)

while (UART_STATUS_REG & (1 << 5)) {
    // 等待发送完成
}
上述代码中,volatile 确保每次循环都从物理地址重新读取状态寄存器,避免因编译器优化导致死循环。若未声明为 volatile,编译器可能只读取一次值并缓存,忽略硬件实际变化。
常见错误场景对比
  • 未使用 volatile:寄存器状态更新不可见,程序逻辑失效
  • 正确使用 volatile:确保每次访问都触发实际内存读写

3.2 在多任务环境或中断中共享数据的保护策略

在多任务系统或中断服务例程中,多个执行流可能同时访问共享资源,导致数据竞争和状态不一致。为确保数据完整性,必须采用有效的同步机制。
数据同步机制
常见的保护手段包括互斥锁、自旋锁和原子操作。对于实时性要求高的中断上下文,通常使用自旋锁避免任务调度。

spinlock_t lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;

spin_lock_irqsave(&lock, flags);
// 临界区:访问共享数据
shared_data++;
spin_unlock_irqrestore(&lock, flags);
上述代码通过 spin_lock_irqsave 禁用本地中断并获取锁,防止被中断抢占,确保原子性。flags 用于保存中断状态,解锁时恢复。
机制对比
  • 互斥锁适用于进程上下文,可睡眠
  • 自旋锁适用于短时间临界区,尤其中断中不可睡眠场景
  • 原子操作适合单一变量的读-改-写操作

3.3 内存映射I/O与硬件状态轮询中的实践案例

在嵌入式系统中,内存映射I/O常用于直接访问外设寄存器。通过将硬件寄存器映射到处理器的内存地址空间,CPU可使用标准的读写指令与设备通信。
硬件状态轮询实现
以下为轮询GPIO按键状态的典型代码:

#define GPIO_BASE 0x40020000
#define GPIO_IDR  (GPIO_BASE + 0x10)

while (*(volatile uint32_t*)GPIO_IDR & (1 << 5)) {
    // 等待按键按下(PD5为低电平)
}
代码中,volatile确保每次读取都访问实际寄存器;位操作检测第5引脚状态。该方式简单可靠,适用于低延迟场景。
性能对比分析
方法CPU占用响应延迟
轮询高低
中断低中

第四章:避免常见陷阱——正确使用volatile的工程规范

4.1 不要滥用volatile:与const和static的组合使用原则

在嵌入式系统和多线程编程中,volatile用于防止编译器优化对内存的访问,确保每次读写都从实际地址获取。然而,滥用volatile不仅影响性能,还可能掩盖设计缺陷。
与const的组合使用
const volatile适用于只读硬件寄存器——值不可被程序修改(const),但可能被外部改变(volatile)。
const volatile uint32_t *REG = (uint32_t *)0x4000A000;
此处指针指向只读寄存器,程序不能写入,但硬件会动态更新其值,两者语义互补。
与static的组合场景
static volatile常用于中断服务中的局部状态标志:
static volatile bool data_ready = false;
该变量驻留静态存储区(static),且在中断中被修改,主线程需实时感知变化(volatile)。
  • volatile 不提供原子性,不能替代锁机制
  • 避免对非内存映射或非并发变量使用 volatile

4.2 volatile无法替代原子操作:并发访问的风险警示

数据同步机制的局限性
volatile 关键字确保变量的可见性,但不保证操作的原子性。在多线程环境下,复合操作如“读-改-写”仍可能引发竞态条件。
典型并发问题示例

volatile int counter = 0;
// 多个线程执行以下方法
void increment() {
    counter++; // 非原子操作:读取、+1、写回
}
尽管 counter 被声明为 volatile,counter++ 包含三个步骤,多个线程同时执行时可能导致丢失更新。
原子操作的必要性
  • volatile 仅保障变量的最新值可见
  • 无法防止多个线程交错执行同一操作
  • 应使用 AtomicInteger 等原子类实现线程安全递增

4.3 使用volatile调试优化导致的“丢失”变量问题

在多线程或中断驱动的程序中,编译器优化可能导致某些变量被错误地“缓存”到寄存器中,从而在外部修改时无法及时反映最新值。这种现象常表现为变量“丢失”更新。
volatile关键字的作用
`volatile`告诉编译器该变量可能在程序之外被修改,禁止将其优化到寄存器中,确保每次访问都从内存读取。

volatile int flag = 0;

void interrupt_handler() {
    flag = 1;  // 中断中修改
}

int main() {
    while (!flag) {
        // 等待中断设置 flag
    }
    return 0;
}
若未声明`volatile`,编译器可能将`flag`缓存至寄存器,导致`while`循环永不退出。使用`volatile`后,每次判断都会重新读取内存中的值,正确响应外部变化。
常见场景对比
场景是否需volatile原因
中断服务程序共享变量是硬件中断异步修改
普通局部变量否无外部修改风险

4.4 嵌入式项目中的代码审查清单与最佳实践

在嵌入式系统开发中,代码质量直接影响系统稳定性与实时响应能力。审查应聚焦资源管理、中断处理和硬件交互等关键环节。
常见审查要点
  • 确保所有指针访问前已初始化
  • 验证中断服务程序(ISR)是否短小且无阻塞调用
  • 检查内存分配是否避免动态堆使用
  • 确认外设寄存器访问具有volatile修饰
典型安全代码示例

// 中断服务函数:仅置位标志,不执行复杂逻辑
void USART1_IRQHandler(void) {
    if (USART1->SR & RXNE_FLAG) {
        rx_complete_flag = 1;  // 仅设置标志
        received_data = USART1->DR;
    }
}
上述代码避免在ISR中调用库函数或延时,减少中断延迟风险。变量rx_complete_flag应在主循环中被检测并清零,实现安全的前后台数据同步。
审查流程建议
阶段动作
预审静态分析工具扫描(如PC-lint)
同行评审双人交叉审查,关注边界条件
集成后回归测试覆盖关键路径

第五章:从volatile到更高级的内存模型:未来嵌入式编程的趋势

在现代嵌入式系统中,随着多核处理器和异构计算架构的普及,仅依赖 `volatile` 关键字已无法满足对内存可见性和执行顺序的精确控制。开发者必须理解底层内存模型,以避免数据竞争和未定义行为。
内存屏障与编译器优化
`volatile` 能阻止编译器优化对特定变量的访问,但不保证CPU核心间的内存一致性。例如,在ARM Cortex-M多核环境中,需显式插入内存屏障指令:

// 确保写操作全局可见
__DMB(); // Data Memory Barrier
flag = 1;
__DSB(); // Data Synchronization Barrier
C11原子操作与可移植性
C11标准引入了 ``,提供跨平台的原子类型和内存顺序控制,显著提升代码可维护性:

#include <stdatomic.h>
atomic_int ready = 0;

// 生产者线程
data = 42;
atomic_store_explicit(&ready, 1, memory_order_release);

// 消费者线程
if (atomic_load_explicit(&ready, memory_order_acquire)) {
    use(data);
}
硬件内存模型对比
不同架构对内存顺序的支持存在差异:
架构内存模型典型屏障指令
x86TSO(全存储序)mfence
ARMv7弱内存模型dmb, dsb
RISC-VRVWMOfence
实时系统中的实践策略
在FreeRTOS或Zephyr等RTOS中,推荐结合信号量与显式内存同步机制。例如,使用事件标志组时,应确保共享数据更新先于事件发布,并通过编译屏障防止重排:
  1. 更新共享缓冲区数据
  2. 插入编译器屏障(__asm volatile("" ::: "memory"))
  3. 设置事件标志触发中断处理
keil编译器的优化问题 关键字volatile的使用 void main(void) { unsigned int y=0x1314; volatile unsigned char yh=0,yl=0; initcpu(); yl=y%256;//取余数得低8位 yh=y/256;//取整得高8位 for(y=0;y<960;) { y+=100; yl=y%256;yh=y/256; } } 上面的代码中,... 阅读详情

相关推荐

单片机中volatile的应用

Python微信订餐小程序课程视频 https://edu.youkuaiyun.com/course/detail/36074 Python实战量化交易理财系统 https://edu.youkuaiyun.com/course/detail/35475 **0****1、**简述 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。 如果没有volatile关键字,则编

weixin_45566993的博客 1075

编译优化那些事儿~

编译优化是指在编译器将源代码转换成可执行文件的过程中,通过一系列的技术手段改善生成代码的性能(如执行速度、内存使用等)。这包括但不限于减少指令数、提高缓存利用率、减少分支错误预测等。// 原始循环i < n;++i) {// 循环展开i < n;i+=4) {

dont worry about it的博客 4217

MySQL8.2.0下载安装

4、点击No thanks,just start my download,就是只是开始下载的意思,点击下载,等待下载完成。5、新建空白行,或直接双击紧挨的空白行,把复制的mysql的安装路径bin路径复制粘贴过来,确定,确定,确定。1、上面点击finish后,自动勾选了run mysql配置,自动会打开配置页面,点击Next。1、双击安装包,进入安装流程,勾选我同意 I accept,next。2、根据自己需要选择,我选的第二个,可以自己改安装路径。2、默认,点击Next,记住默认端口3306。

m0_59681797的博客 1万+

《你真的了解C++吗》No.008:volatile——编译器优化的止步

volatile解决的是编译器优化带来的问题。Mutex解决的是 CPU 乱序执行和多线程并发带来的问题。在 C++03 时代,由于缺乏标准的原子库,开发者确实经常滥用volatile配合特定的编译器扩展(如 MSVC 的volatile在某些版本下确实提供了内存屏障)来进行多线程编程。但在现代 C++ 标准下,请把volatile留给硬件驱动和信号处理,把多线程任务交给。变量前面除了const和volatilestatic。但你知道吗?static。

腾TO的技术博客 1063

fMRI独立成分分析方法(ICA)工具GIFT

详细介绍了进行fmri数据进行ICA分析的工具包GIFT的使用,和进行ICA分析的流程。

m0_58256026的博客 1万+

电子数据取证实战:从“平航杯”竞赛看计算机检材分析的关键技术与案例解析

本文通过'平航杯'电子数据取证竞赛案例,深入解析计算机检材分析的关键技术,包括USB设备追踪、浏览器历史分析、AI换脸取证、虚拟货币交易追踪等实战技巧。重点探讨了数字痕迹的发现与关联,以及电子取证工具链的应用,为从业人员提供实用的技术参考和案例分析。

www00的博客 537

浅析代码优化——编译器优化原理

开篇 相信有过编码经验的人都知道,程序的正常运行,只是最基本的要求。更多的,还要考虑程序的性能,运行效率,组织结构,和重用性等等。 今天将简单的讨论一下如何优化程序性能。 要写出高效的程序,可能多数初学者想到的是在程序中用合适的算法和数据结构。这确实是一中提高程序性能的主要方法。 而这里要讨论的是另一种方法,也是很多人都忽略但确实很重要的方法。也是我们这篇文章的主题: 如何编写出编译器能

John_ToStr的博客 9794

《网络摄像机实战⑦:嵌入式端AWS KVS IoT SDK 库编译与测试全流程-君正/瑞芯微/全志(超详细指南)》

本文介绍了AWS音视频和物联网解决方案的核心组件与集成方法。主要内容包括:1)Amazon Kinesis Video Streams(KVS)提供的WebRTC托管服务,支持实时音视频流传输与双向交互;2)AWS IoT云服务实现设备连接与集成;3)详细说明了KVS WebRTC库的编译过程,包括源代码下载、CMake配置和依赖库生成;4)KVS Producer库的集成方法,重点阐述了存储空间调整和mbedtls版本适配等关键修改点。文章为开发者提供了AWS音视频和物联网服务的技术实现指南,特别针对嵌入

lvj_158的专栏 109

笔记之编译器优化(volatile关键字)问题

一、碰到的问题 前段时间在编写代码的时候,碰到这个问题,我在中断中对变量赋值 RE_Flag=1,然后在其他的一个任务中执行这行代码while(RE_Flag==0){},按照我的理解:这个任务中会等待RE_Flag=1时,然后才会执行后面的代码,但是我调试发现,程序一直卡在 while(RE_Flag ==0){}这行代码,但是RE_Flag这个变量已经变成了1,但是为什么一直卡在while这呢? 二、变量关键字 用volatile关键字是防止变量被编译器优化 volatile 是在C ,C++,Java

尘缘里的记忆的博客 2055

GTSAM | gtsam::ISAM2

本节简单介绍`gtsam::ISAM2`类。

九七的博客 734

安装并新建windows下wxwroks7.0 bootrom工程

安装licence,将zwrsLicense-vx7-perm.lic粘贴到安装目录C盘WindRiver/license下。现在双击Workbench 4,新建vxworks7.0工程,会出现下面的情况,因为没有licence。编译完成binaries下生成wxwroks x86格式,可以修改bootrom硬件信息的配置了。单击x86_wxwroks工程右键,build project编译工程。双击桌面Workbench 4打开,新建windows下工程。新建完成,选择finish。

wangjie36的博客 1922

单片机volatile关键字的作用?

单片机c语言的volatile有什么用?在什么场景用?

无际单片机编程 4073

用AList挂载网盘,无损看VR电影教程,无需下载到PICO头显本地!

用AList挂载网盘 + WebDAV直连头显,看片像拉本地一样流畅,不怕卡顿、不怕没空间,简直是VR看片刚需配置!别再用U盘传电影了,用AList + WebDAV,直接流畅看4K,看片效率翻倍,体验提升一个档次!

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 5545

c语言编译器怎么防止优化变量,volatile关键字的作用:防止变量被编译器优化

volatile关键字是一种类型修饰符,用它声明的类型变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。 精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。其中关键在于两个地方:1.编译器的优化在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就...

weixin_28607671的博客 8516

pycharm报错cannot start the IED:Error occurred during initialization of VMagent library failed...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1925

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

编程中什么情况下需要加 volatile?

简单来说,

qq_41854911的博客 8263

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

c语言volatile关键字在单片机中的作用

c语言volatile关键字在单片机中的作用 volatile 的意思是“易失的,易改变的”。这个限定词的含义是向编译器指明变量的内容可能会由于其他程序的修改而变化。通常在程序中申明了一个变量时,编译器会尽量把它存放在通用寄存器中,例如ebx。当CPU把其值放到ebx中后就不会再关心对应内存中的值。若此时其他程序(例如内核程序或一个中断)修改了内存中它的值,ebx中的值并不会随之更新。为了...

ll148305879的博客 1855

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

单片机开发 volatile 至关重要的作用

关注+星标公众号,不错过精彩内容作者 | strongerHuang微信公众号|strongerHuang单片机开发初学者可能不怎么关心编译器优化的功能,但对于经验丰富的工程师来说,掌握代码优化是必备技能。今天讲述的话题就是关于代码优化中,关键字volatile在优化过程中起到的作用。分享正文之前推荐一个嵌入式招聘信息的平台:什么是‍‍volatile?volatile是一个类型修饰符(typ...

strongerHuang 1198

单片机开发中的volatile

具体来说,volatile声明的变量可能会被外部环境或其他代码(如硬件中断、外设寄存器等)意外修改,因此编译器必须每次都直接从内存中读取该变量的值,而不能将其缓存到寄存器中。特别是在多个线程或中断中共享的全局变量,由于其可能在不确定的时间被修改,如果没有volatile修饰,编译器可能会假设这些变量在某一段时间内不会发生改变,从而进行不合理的优化,最终导致代码无法按照预期运行。在单片机开发中,变量的值可能会受到外部硬件的影响而变化,或者在多线程程序中被不同的线程修改。

硬核科技 1302

volatile为什么要修饰中断里的变量

先来个总的介绍: volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int

fengyunjh6的专栏 7872

C语言volatile用法/Keil编译器优化/delay被编译器优化

*有的小伙伴可能看到这里会很懵,CPU访问变量不就是访问内存中的实际变量吗,并不是这样的,CPU内部还有寄存器,CPU读写寄存器的速度是远大于读写内存的速度,为了提高程序的执行速度,编译器会优化代码,把实际的变量存放到寄存器中,通过读写寄存器来访问该变量。加了volatile关键字的delay函数,使用-O2优化等级,执行速度比不加volatile关键字的delay函数(使用-O0优化)还慢,说明了使用-O0优化编译器仍然会作一定优化。补充实验,声明变量count时也加入了volatile关键字,

weixin_45379397的博客 1989

volatile关键字的作用:防止变量被编译器优化

本文大部分来自于:http://witmax.cn/volatile.html 我怕链接会失效,故转载此篇文章。。。 volatile关键字是一种类型修饰符,用它声明的类型变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。 其中关

Tim的嵌入式之旅 7298

C语言 volatile的作用与使用场景

今天完成公司的任务,突然想起来在调试过程中遇到了一个问题是这样的:“我在主函数里面写了一个while(x)的循环,想在中断里面去改变这个变量x,以达到主函数里面退出while循环的目的。但是结果并不是这样的,我的代码一直停在了while循环里面。后面我咨询了一位大哥,然后他告诉我在变量i前面加上一个volatile。果然,代码运行和我的预期一样了”。代码如下 void main() { ...

Xm行墨的博客 3619

【STM32】__IO(volatile)在单片机定时器编程中的作用

__IO(volatile)避免了代码优化,更保证了数据可以正常地读写以及系统功能的实现

qq_26923297的博客 1980

编译器优化 之volatile关键字

C/C++ 的volatile volatile是在C,C++,Java等中语言中的一种修饰关键字。 这个关键字在嵌入式系统中,是一个非常重要的一个使用。尽管在一般的Application中,可能很多人都不需要使用这个。但是在单片机中,如果不熟悉这个关键字,很有可能产生想像不到的意外。 那么,我就来谈谈Volatile的意义--volatile在ANSIC(C89)以后的C标准规格和const一...

chuiziky的专栏 795
上一篇: C语言中数组传参必须传长度?真相令人震惊的2种替代方案
下一篇: 内存对齐如何毁掉你的程序性能?C语言联合体避坑全攻略
SimCompile
博客等级 码龄1年 140粉丝 2012原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值