C语言关键字之“volatile”

发布于:2025-03-27 ⋅ 阅读:(40) ⋅ 点赞:(0)

目录

一、回顾

二、 寄存器为什么是没有地址的?

 三、C语言中变量的访问

四、volatile关键字(编译器实现的)


一、回顾

C语言中变量的定义
存储类型 特征修饰 数据类型 变量名
决定变量的存储位置 决定变量的特征属性                                      决定变量的存储空间及数据范围 决定变量的引用标识

auto、static、extern、registor

const(修饰的变量只能读,不能写,不是常量,还是变量,只是变量的属性改了)、volatile char、int、short、float、double、long等 自己定义
eg;static volatile int value;

总结
存储类型 修饰的变量存储位置
auto 只能修饰局部变量,存储在栈区
static 修饰全局/局部变量,存储在静态区。延长生命周期,修饰的全局变量/函数只能在本文件内使用。初始化的全局变量存储在DATA段,未初始化的全局变量存储在BSS段
extern 只能修饰全局变量,存储在DATA段
registor 只能修饰局部变量,只能修饰“整型”数据类型,存储在CPU内部的寄存器中。不能进行取地址(&)操作,因为寄存器是没有地址的

二、 寄存器为什么是没有地址的?

寄存器被认为没有地址的原因主要可以从以下几方面理解:

  1. 硬件层面寄存器是 CPU 内部的存储单元,用于快速访问和处理数据。由于寄存器属于处理器的硬件结构,CPU 对它们的访问速度远快于内存,因此它们通常不需要像内存单元一样被寻址。

  2. 逻辑模型:在 C 语言和其他高级编程语言中,编程人员较少直接与寄存器交互,通常使用变量和数据结构。寄存器的存在主要是为提高程序执行效率,而不是为了被程序员显式寻址。因此,在高层次的编程中,寄存器的地址并不重要。

  3. 编译器优化:编译器在生成机器代码时会自行决定将哪些变量存放在寄存器中,具体的存放位置和数量也可能根据执行时的状态而变化。因此,寄存器的“位置”在编译时并不固定,程序员也无法直接引用。

  4. 缺乏支持:在大多数编程语言和操作系统中,没有机制用于直接访问寄存器的地址。虽然有些低级语言(如汇编语言)允许直接操作寄存器,但这一操作通常不涉及寻址概念。

        综上所述,寄存器由于其高速存取和硬件特性,被设计为无需地址的存储单元,使得 CPU 在执行指令时能够迅速处理数据。

 三、C语言中变量的访问

C语言中变量的访问
1、读变量 内存->寄存器(CPU)
2、写变量 寄存器(CPU)->内存
3、典型实例:

        C语言                              汇编语言

        int a, b;                             //为a,b申请内存

        a = 1;                               //1->寄存器

                                                //寄存器->内存(&a)

        b = a;                               //内存(&a)-> 寄存器

                                                //寄存器->内存(&b) 

四、volatile关键字(编译器实现的

        volatile的意思即为“易变的”,在C语言中当使用volatile修饰一个变量时,即表示这个变量的值随时都有可能发生改变,因此编译器在编译的时候对该变量的存取操作不能进行优化,即告诉编译器每次存取该变量的时候都要从内存中去存取而不是使用其之前在寄存器中的备份。

volatile int a =1,b,c; //为a,b,c申请内存并初始化
b = a; //内存(&a)->寄存器(CPU)
//寄存器(CPU)->内存(&b)
c = a; //内存(&a)->寄存器(CPU)
//寄存器(CPU)->内存(&b)

//内存(&a)->寄存器(CPU)此步骤能否被优化?看a值是否变化

那么哪种情况有可能导致a值会改变呢?(即volatile应用场合)

        中断只是一个CPU,但是多线程可能是不同的CPU(一个进程有两个线程,分别为线程1和线程2,现在大部分都是多核处理器(CPU),也可能两个线程同时执行。线程1可能会在CPU1中执行,线程2可能会在CPU2中执行)

1)中断(硬件机制)

        中断服务程序中若修改其他程序中使用的变量,需要volatile修饰该变量;

        中断跟其他普通的子程序不一样,子程序什么时候执行你是知道的,但是中断什么时候执行,不一定,随时都有可能执行!

2)多线程

        多个线程都要访问的变量一般需要加volatile修饰;(Linux中)

3)硬件寄存器

        硬件寄存器的值有可能会随着硬件工作状态的变化而变化,需要加volatile修饰。例如:ADC电压转化的使用,读取到的电压值是实时变化的。


网站公告

今日签到

点亮在社区的每一天
去签到