嵌入式科普(33)深度解析C语言中的const和volatile关键字
1. 关键字基础概念
-
const:定义"只读变量",被修饰的变量不可被程序修改
-
volatile:提醒编译器该变量可能被意外修改,禁止编译器优化
-
九、e2studio VS STM32CubeIDE之const修饰BSP函数的形参
嵌入式科普(23)指向寄存器的指针变量1 注意强制类型转换
嵌入式科普(32)指向寄存器的指针变量2---可变指针 volatile int* volatile p;货真价实
2. 修饰普通变量
类型 | 示例 | 可变性 | 初始化 要求 | 访问特性 | 典型应用场景 |
---|---|---|---|---|---|
普通变量 | int a; | ✔️ | 无要求 | 常规访问 | 普通变量存储 |
const变量 | const int a = 10; | ❌ | 必须立即 初始化 | 值固定不变 | 常量定义/参数保护 |
volatile变量 | volatile int b = 20; | ✔️ | 建议初始化 | 每次访问都 从内存读取 | 硬件寄存器/多线程 |
const volatile变量 | const volatile int c; | ❌ | 建议初始化 | 值不可改 但可能外部变化 | 只读硬件寄存器 |
volatile const变量 | volatile const int d; | ❌ | 建议初始化 | 同上(语法等价) | 同上 |
3. 修饰指针变量(经典组合)
-
const与指针
类型 | 示例 | 指针 自身可变 | 数据 可变性 | 典型用途 |
---|---|---|---|---|
普通常量 | const int a=10; | - | ❌ | 全局常量、参数保护 |
指向常量的指针 | const int* p; | ✔️ | ❌ | 传递不可变数据 |
常量指针 | int* const p=&x; | ❌ | ✔️ | 固定地址的读写操作 |
双重常量指针 | const int* const p; | ❌ | ❌ | 完全只读访问 |
核心逻辑:
🔒 const 在 * 左侧 → 数据不可变
🔒 const 在 * 右侧 → 指针不可变
-
volatile与指针
类型 | 示例 | 访问 特性 | 优化 禁止范围 | 典型场景 |
---|---|---|---|---|
普通易变变量 | volatile int cnt; | 数据强制刷新 | 变量缓存优化 | 多线程共享变量 |
易变数据指针 | volatile int* p; | 数据强制刷新 | 数据访问优化 | 硬件寄存器访问 |
易变指针 | int* volatile p; | 指针地址 强制刷新 | 指针缓存优化 | 中断修改的指针 |
双重易变指针 | volatile int* volatile p; | 双重强制刷新 | 全路径优化 | 动态硬件配置 |
核心逻辑:
⚡ volatile 在 * 左侧 → 数据访问不可优化
⚡ volatile 在 * 右侧 → 指针地址访问不可优化
-
联合使用
// 嵌入式开发中的只读硬件寄存器(数据不可改,但值可能被硬件改变)
const volatile uint32_t* REGISTER = (volatile uint32_t*)0x40000000;
4. 典型应用场景
const的常见使用:
-
保护函数参数不被修改
-
定义只读的全局常量
-
与指针配合实现不同级别的保护
volatile的常见使用:
-
硬件寄存器访问
-
多线程共享变量
-
信号处理程序中的变量
5. 注意事项
-
const变量必须初始化
-
volatile不保证原子性
-
可同时使用const和volatile修饰(如只读的硬件寄存器)
-
类型转换时需注意const修饰符的去除