[C语言] “变量的完整定义“ & “volatile关键字“
1. 变量的完整定义
1.1 介绍
?变量的定义很多都会被省略, 这里详解.
存储类型? ? 特征修饰? ? 数据类型? ? 变量名
eg:
static? volatile? int? ?value; //静态易变的整型变量value;
- 存储类型: 决定了变量的存储位置
- 特征修饰: 决定了变量的特殊属性
- 数据类型: 决定了变量的存储空间和数据范围
- 变量名称: 决定了变量的引用标识
?1.2 四种存储类型关键字
关键字 | 描述 | 存储位置 |
auto | 自动, 不写默认是这个, 只能修饰局部变量. 临时使用, 不使用的时候会被编译器销毁. | 栈区 |
register | 建议编译器将变量存储在CPU的寄存器中, 但是不一定, 也可能在内存中.?修饰局部变量并且必须是整型. | CPU寄存器 / 内存 |
static | 可以修饰局部变量和全局变量. 生命周期持续整个程序结束. | 存在静态区或数据段 |
extern | 存储在其他文件, 告诉编译器这个变量已经在其他文件申请了一块儿空间, 没必要再申请空间了. | 告诉编译器不用给它申请空间. |
全局变量比较特殊, 初始化过的存在全局数据区, 没有初始化过的存在BSS区
堆是程序员申请, 程序员释放. 栈是编译器申请, 编译器释放.?
1.3 两种特征修饰
关键字 | 描述 |
const | 让修饰的变量只读. |
volatile | 后面详细介绍. |
2. C语言中变量的访问
2.1. 读变量?
内存 --> 寄存器(CPU)?
例如:
int a, b;
a = 1;? ?
b = a;? //读取a
- 在内存中(*(&a)) --> 寄存器
- 寄存器 --> 内存(&b)
2.2. 写变量
寄存器(CPU)? --> 内存
例如:
int a, b;
a = 1;? ?
b = a;? //写入b
- 在内存中(*(&a)) --> 寄存器
- 寄存器 --> 内存(&b)
3. 代码优化
?在计算机工作时, 内存的访问速度远不及CPU的处理速度, 为了提升计算机的整体性能, 在软硬件层面都有相应的机制去优化内存的访问. 方案如下:
- 硬件层面: 引入高速缓存(Cache)
- 软件层面:?
- 编码优化(程序员) : 个人能力.
- 编译优化(编译器) : 很多, 与volatile相关如下例子所示(汇编指令).
//编译器优化, 减少了读取变量的时间
int a = 1, b, c;? //为a, b, c申请内存, 并给a初始化为1
b = a;??????????????// 读取a地址的内容? --> 寄存器x? ? ?寄存器x --> 写入b的内存
c = a;? ? ? ? ? ? ? //寄存器x --> 写入c的内存?
//不优化, 增加了读取变量的时间
volatile int a = 1, b, c;? //为a, b, c申请内存, 并给a初始化为1
b = a;??????????????????????????// 读取a地址的内容? --> 寄存器x? ? ?寄存器x --> 写入b的内存
c = a;? ? ? ? ? ? ? ? ? ? ? ? ? // 读取a地址的内容? --> 寄存器x? ? ?寄存器x --> 写入c的内存?
4. volatile关键字
4.1 介绍?
?volatile的意思是 "易变的" , 在C语言中当使用volatile修饰一个变量时, 即表示这个变量的值随时都有可能发生改变, 因此编译器在编译的时候对该变量的存取操作不能进行优化, 即告诉编译器每次存取该变量的时候都要从内存中去存取而不是使用其之前在寄存器中的备份.
有哪些情况会导致a发生变化, 多线程(RTOS中的任务就是单核多线程的关系), 中断, 硬件寄存器.
4.2 应用场合
- 中断: 中断服务程序中若修改其他程序中使用的全局变量可能会导致突变. 需要使用volatile修饰.
- 多线程: 多个线程都要访问的变量一般需要加volatile.
- 硬件寄存器: 硬件寄存器的值有可能会随着硬件工作状态的变化而改变, 需要使用volatile修饰.
4.3 优缺点
优点很明确, 读取的数据都是实时的准确的.
缺点是无法得到编译器的优化, 增加CPU的执行时间, 影响效率, 因此在不需要优化的地方, 不要使用volatile关键字.
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!