*——const 绑定它;若 const 在最左边(左边没东西),则绑定右边一句话:"const 挨着谁,谁就是只读的。"
const 禁止修改它绑定的对象。它既是给程序员的规范(编译期检查,防止误改),也会影响生成的代码(嵌入式里 const 数据进只读段 rodata/Flash,不占 RAM)。
const int x = 5; → const 在最左边 → 绑定右边 int → x 不能改const int *p; → const 最左边 → 绑定 int → "指向常量的指针":*p 不能改,但 p 可以指向别处int *const p; → const 左边最近是 * → 绑定指针 → "常量指针":p 不能再指向别处,但 *p 可以改int const *p; → const 左边最近是 int 不是 * → 绑定 int,与 const int *p 完全等价(很多人误以为和 int *const 有关)int *p; → 无 const,指针和值都能改| 写法 | 读法 | 不能改谁 | 能改谁 |
|---|---|---|---|
const int *p |
指向常量的指针 | *p(值) |
p(指针) |
int *const p |
常量指针 | p(指针) |
*p(值) |
const int *const p |
两者都 const | 都不能改 | 都不能改 |
记忆锚点:const 离谁近,谁就不能动。 const int *p 里 const 挨着 int → 值是死的;int *const p 里 const 挨着 * → 指针是死的。
int const *p = &a; → p = &b; 合法(const 绑定 int,p 能改指向);*p = 10; 不合法(值不能改)int *const q = &c; → q++; 不合法(指针不能改);*q = 20; 合法(值能改)void show(const int *r) { r = &b; ... } → r = &b; 合法(很多人误以为 const 让指针也不能改,实际绑定的是 int);*r = 99; 不合法const int *p 和 int const *p 等价(都绑定 int),int *const p 绑定指针const char *str = "hello";——字面量本来就存在只读区,直接改是未定义行为(通常运行时崩溃/段错误)。加 const 让编译器在编译期就拦住你,而不是等到运行时炸;去掉 const 代码能编过,但一改就崩int const *p 不等于 int *const p;字符串的 const 主要价值是编译期拦截对只读区的非法修改| 相邻概念 | 和 const 的关系 | 孤立理解会犯的错 |
|---|---|---|
| volatile | 防不同敌人:const 防程序员改,volatile 防编译器缓存,可共存于只读寄存器 | 以为 const=volatile,或以为二者互斥 |
| #define | #define 文本替换、无类型检查;const 有类型、进只读段 | 以为宏能替代 const——宏改不了内存布局,也查不出类型错 |
| static | static const 组合 = 文件内只读常量,嵌入式常用 |
以为 const 自带 static 的文件隔离效果 |
| 指针 | 三种写法 = const 绑定 int / 绑定 * / 两者都绑 | 一看到 int const *p 就以为 p 不能动 |
2026-08-03
每主题一页,复习时只翻本目录。