• C语言volatile解析


    在百度百科中volatile关键字是这样解释的:

    volatile是一个特征修饰符(type specifier)。volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。一般在以下场景中使用:

    • 并行设备的硬件寄存器(如:状态寄存器)
    • 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
    • 多线程应用中被几个任务共享的变量

    仅看上述内容总感觉让人不够直观,与其绞尽脑汁去细品,不如直接写段代码,看看无volatile和带volatile的变量在编译后生成的汇编代码有哪些区别。

    因为笔者相对熟悉arm平台,所以选用了armcc编译器,版本为:ARM Compiler 5.06 update 6 (build 750),优化等级为O3,操作系统平台为Windows 10.0.18362,具体编译命令如下:

    armcc.exe -O3 -S D:volatile测试volatile.c -o D:volatile测试volatile.s

    无volatile代码如下:

    int a=1;
    int b=2;
    int c;
    int main()
    {
        b=a;
        c=b;
        return 0;
    }

    使用volatile修饰变量b,修改后的代码(带volatile)如下:

    int a=1;
    volatile int b=2;
    int c;
    int main()
    {
        b=a;
        c=b;
        return 0;
    }

    无volatile代码生成的关键汇编(部分)如下:

    main PROC
            LDR      r0,|L0.24|
            LDR      r1,[r0,#0]  ; 将变量a载入到寄存器r1
            STR      r1,[r0,#4]  ; 将寄存器r1存储至变量b
            STR      r1,[r0,#8]  ; 将寄存器r1存储至变量c
            MOV      r0,#0
            BX       lr
            ENDP

    而带volatile代码生成的汇编如下:

    main PROC
            LDR      r0,|L0.28|
            LDR      r1,[r0,#0]  ; 将变量a载入寄存器r1
            STR      r1,[r0,#4]  ; 将寄存器r1存储至变量b
            LDR      r1,[r0,#4]  ; 将变量b载入寄存器r1
            STR      r1,[r0,#8]  ; 将寄存器r1存储至变量c
            MOV      r0,#0
            BX       lr
            ENDP

    对此,我们可以清楚的发现:在未使用volatile的汇编代码中,当变量b赋值给变量c时,直接将寄存器r1更新至变量c;而在使用volatile修饰变量b以后,同样变量b赋值给变量c时,先把变量b的值更新至寄存器r1(强制更新,红底色代码),再把寄存器r1更新至变量c。使用volatile修饰的变量会被编译器标记为易改变的变量,编译器在处理该变量赋值操作时会添加同步该变量(内存)至寄存器的操作。

  • 相关阅读:
    jni java与c++交互返回三维数组jobjectArray
    Android开发之EditText 详解(addTextChangedListener监听用户输入状态)
    Android JNI和NDK学习(09)--JNI实例二 传递类对象
    JavaDoc的生成规则---ShinePans
    Android 电话自己主动接听和挂断具体解释
    传统线程技术(一)
    Linux内核启动及根文件系统载入过程
    eclipse、MyEclipse实现批量改动文件编码
    菜鸟开发—应具备的搜索技巧
    Java之GUI编程(一)
  • 原文地址:https://www.cnblogs.com/randyjang/p/12333749.html
Copyright © 2020-2023  润新知