const
表示变量的值不可被修改。这对防止意外写操作、明确意图和让编译器更好地优化有重要作用。在大多数嵌入式编译器(如 Keil、GCC)中,加了 const
的数据可以被放入只读区域(ROM/Flash),节省宝贵的 RAM。
const int a = 5;
a = 10; // ❌ 错误:尝试修改 const 值
嵌入式中使用 const
的典型场景
1. 定义只读配置参数
//系统主频、设备ID、初始化常量等的值固定、不应被改动。
const uint32_t system_clock = 16000000;
2. 修饰函数参数,避免误操作
修饰传入变量,防止修改
void print_config(const char* str) {
printf("%s\n", str); //str 指向的内容不能被修改,防止误写。
}
void modify(char* str) { str[0] = 'x'; } // 可以修改内容
void modify(const char* str) { str[0] = 'x'; } // ❌ 编译错误
3. 修饰数组(查表)常量
查表法(LUT)是嵌入式中常用优化手段:
//放在 Flash 中,不占用 RAM,并避免被修改。
const uint8_t crc_table[256] = {
0x00, 0x07, 0x0E, 0x09, // ...
};
4. 配合指针修饰,控制读写权限
理解下面 3 种指针写法在嵌入式中非常重要:
声明方式 | 含义 |
---|---|
const int* p | 指向的内容不可改 (*p = 5; 错误),但可以指向别的地址 |
int* const p | 指针本身不可改(p = other; 错误),但可以修改 *p |
const int* const p | 指针和内容都不可改 |
const int val = 10;
const int* p = &val; // OK
*p = 20; // ❌ 不允许
结合 volatile
使用(高级用法)
在一些寄存器场景中,可以使用 const volatile
:
#define STATUS_REG (*(const volatile uint32_t*)0x40000010)
关键字 | 意义 |
---|---|
volatile | 每次都要从真实地址读取 |
const | 不能修改内容(比如只读状态寄存器) |
✅ 六、错误理解 & 开发建议
❌ 常见误解:
-
认为
const
是完全只读(指针情况更复杂) -
忽视
const
在 RAM/ROM 优化的作用 -
不在查表和配置中使用
const
✅ 建议:
-
配置表、LUT、静态参数都要加
const
-
所有函数的输入参数,只要不需要写,就加
const
-
学会写复杂指针修饰组合(比如
const uint8_t* const p
)
✅ 总结
使用位置 | 意图 |
---|---|
全局常量 | 放入 Flash,节省 RAM |
函数参数 | 明确只读、防止误操作 |
查找表 | 提升性能、代码安全 |
寄存器访问 | 与 volatile 联合使用 |
指针修饰 | 控制访问粒度 |