<p>指针变量声明需注意属于类型而非变量名修饰符,int p, q;中仅p为指针;空指针应优先用nullptr;const位置决定修饰对象;数组指针与指针数组括号位置关键。</p>

指针变量声明的基本语法
声明指针变量的关键是 * 的位置和类型匹配,不是写在变量名前就万事大吉——它属于类型的一部分,而非变量名修饰符。比如 int* p; 和 int *p; 等价,但 int* p, q; 实际只让 p 是指针,q 是普通 int,这点极易误读。
常见错误现象:int* p, q; 被当成两个指针,结果 q 无法解引用;或把 int *p = &x; 写成 int* p = x;(漏掉 &),编译报错 cannot convert 'int' to 'int*' in initialization。
- 每个指针变量需单独声明:用
int *p, *q;,而不是int* p, q; - 声明时可初始化,但必须用地址:如
int x = 42; int *p = &x;,不能直接赋值整数 -
const位置决定修饰对象:int* const p = &x;(指针不可变)、const int* p = &x;(所指内容不可变)
声明空指针的推荐写法
C++11 起,应优先用 nullptr 声明空指针,而非 NULL 或字面量 0。前者是类型安全的纯右值,后者可能被误推导为 int,引发函数重载歧义。
例如有重载函数 void foo(int) 和 void foo(char*),调用 foo(NULL) 会匹配 foo(int),而 foo(nullptr) 明确匹配指针版本。
立即学习“C++免费学习笔记(深入)”;
- 正确写法:
int *p = nullptr;、int *q{};(值初始化也为nullptr) - 避免:
int *p = NULL;(NULL通常是0或0L,非指针类型) - 不推荐:
int *p = 0;,同样存在类型推导风险
声明指向 const 数据的指针 vs const 指针
这俩概念常混,但语义完全不同,声明时 const 紧邻哪边,就修饰哪边。
const int *p; 等价于 int const *p;:指针可改(p++ 合法),但不能通过 *p = 5; 修改所指内容;int *const p = &x;:指针本身不可再赋值(p = &y; 报错),但 *p = 10; 合法。
- 记忆口诀:“从右往左读”:
int *const p→p是const指针;const int *p→*p是const int - 双重 const:
const int *const p = &x;,指针和所指内容都不可变 - 声明后若违反约束,编译器直接报错,如
error: assignment of read-only location '*p'
数组指针与指针数组的声明差异
名字像、写法近,但含义天差地别:int (*p)[5]; 是“指向含 5 个 int 的数组的指针”,而 int *p[5]; 是“含 5 个 int* 的数组”。括号位置决定优先级。
典型误用:想声明一个存放 5 个指针的数组,却写了 int* p[5];(正确),但读作“p 是指向数组的指针”,实际它是数组;反过来,int (*p)[5] = &arr; 中 arr 必须是 int arr[5] 类型,否则类型不匹配。
-
int *p[5];→p是数组,每个元素是int*;等价于typedef int* ptr_t; ptr_t p[5]; -
int (*p)[5];→p是指针,指向int[5];必须用取址符初始化:int arr[5]; int (*p)[5] = &arr; - 混淆会导致
sizeof结果差一个数量级,且解引用行为完全错误
声明指针看似简单,真正容易出问题的是类型精度、const 语义和括号绑定顺序——这些地方一错,轻则编译失败,重则运行时未定义行为,而且往往要到调用链深处才暴露。


















