<p>常量指针是const int ptr,指针可变但所指数据不可改;指针常量是int const ptr,指针本身不可变但所指数据可改;双重constconst int* const ptr则二者均不可变。</p>

常量指针:int* const ptr 还是 const int* ptr?
很多人被“常量指针”这个中文词误导,以为是指针本身不可变——其实它描述的是“指向常量的指针”,即指针可改,但不能通过它修改所指对象。正确写法是 const int* ptr(等价于 int const* ptr),const 修饰的是 int,不是 *。
常见错误:把 int* const ptr 当作“常量指针”来用,结果发现指针不能改、值却能改——这其实是“指针常量”,不是你要的。
-
const int* ptr = &x;→ptr可以指向别的地址(ptr = &y;合法),但不能执行*ptr = 5;(编译报错:assignment of read-only location) - 初始化后可重新赋值指针本身:
ptr = &z;是允许的 - 函数参数中常用这种形式保护输入数据,比如
void func(const char* s),防止意外修改字符串内容
指针常量:int* const ptr 的行为和限制
int* const ptr 才是真正“指针不可变”的类型:指针变量本身是 const,初始化后不能再指向别处;但它指向的值可以修改(只要原变量不是 const)。
关键点在于 const 紧贴 * 左侧时修饰指针本身;紧贴类型名左侧时修饰所指类型。读法建议从右往左:`ptr is const pointer to int`。
立即学习“C++免费学习笔记(深入)”;
- 必须初始化:
int* const ptr = &x;—— 不初始化会编译失败(uninitialized const variable) -
ptr = &y;是非法的,编译器直接拒绝 -
*ptr = 10;合法(前提是x本身非常量) - 常用于绑定硬件寄存器地址或只读配置结构体指针,确保指针不被意外重定向
两者组合:const int* const ptr 是什么?
当既要禁止修改指针,又要禁止修改所指值,就用双重 const:const int* const ptr = &x;。这时指针和它指向的内容都不可变。
容易踩的坑是漏掉其中一个 const,或者误以为加一个就能锁住全部。编译器不会帮你补全——少一个,对应的操作就可能意外通过。
-
ptr = &y;→ 错误:assignment of read-only variable 'ptr' -
*ptr = 5;→ 错误:assignment of read-only location - 注意:
const位置不能交换顺序,int const* const ptr等价,但const int const* ptr是语法错误 - 这种双重 const 在嵌入式或驱动开发里较常见,比如映射到只读内存区域的指针
为什么 typedef 或 using 容易翻车?
用类型别名简化声明时,const 的作用对象极易混淆。例如:
using IntPtr = int*; const IntPtr p = &x; // 等价于 int* const p,不是 const int*
这里 const 修饰的是别名展开后的整个类型(即指针),而不是底层 int。想表达“指向 const int 的指针”,必须显式写出:const int* p 或 using ConstIntPtr = const int*。
- 别名 +
const总是作用于别名代表的“整体”,不是其内部成分 - C++11 起推荐用
using替代typedef,但二者在 const 处理上行为一致 - 模板类型推导(如
auto)也会受此影响:auto p = &x;推出int*,auto const p = &x;推出int* const
实际写代码时,别图省事用别名套 const,老老实实写全 const int* const 更安全。多敲几个字符,比调试半天指针意外被改要强。


















