<p>指针变量p与它指向的值通过&和的位置区分:声明int p中属类型,p是int型变量;&x取x地址赋给p,p访问x的值;p有独立地址&p,p是int型值,非地址。</p>

看变量声明和取地址操作符 & 的位置
区分指针变量和它指向的值,最直接的方式是盯住 & 和 * 出现在哪、作用在谁身上。声明时 int* p; 中的 * 属于类型的一部分,说明 p 是一个指针变量;而运行时 &x 表示“取变量 x 的地址”,得到的值可以赋给 p;*p 则表示“去 p 存的地址里读/写数据”,这个结果就是它指向的值。
常见混淆点:
- 把
int* p = &x;误读成“p等于x的地址” —— 实际上这是对的,但容易忽略:此时p本身有自己独立的内存地址(比如&p),和&x完全不同 - 看到
*p = 5;就以为是在改p,其实是在改p所指向的那个内存单元里的值(也就是x) - 误以为
p和*p类型相同 ——p是int*类型,*p是int类型
用 printf 或 cout 打印地址和值对比
运行时最不绕弯的验证方式,就是同时输出变量地址、指针变量本身、以及解引用结果:
int x = 42;
int* p = &x;
printf("x 的地址: %p\n", (void*)&x); // 输出 x 的内存地址
printf("p 的值: %p\n", (void*)p); // 输出 p 存的地址(应与上行一致)
printf("p 的地址: %p\n", (void*)&p); // 输出 p 自己的地址(完全不同)
printf("*p 的值: %d\n", *p); // 输出 42
关键结论:
立即学习“C++免费学习笔记(深入)”;
-
p的值 =&x(即它存储的是x的地址) -
&p是另一个地址,属于指针变量p自己的存储位置 -
*p不是地址,是int值,和x完全等价(可读可写)
注意空指针、野指针导致的误判
当指针未初始化或已被 delete 后还继续用 *p,程序可能崩溃或返回垃圾值,这时你看到的“指向的值”根本不可信。这不是区分问题,而是安全前提:
-
int* p;声明后未赋值 →p是野指针,*p行为未定义 -
int* p = nullptr;或int* p = NULL;→p是空指针,*p直接段错误 - 必须确保
p指向一块有效、未释放、可访问的内存,*p才真正代表那个位置的值
结构体成员或数组元素场景下的典型陷阱
在复合类型中,& 和 * 容易嵌套,稍不注意就搞混目标:
-
struct S { int a; }; S s; int* p = &s.a;→p是指针变量,*p等价于s.a,不是s -
int arr[3] = {1,2,3}; int* p = arr;→ 这里arr自动退化为指针,p指向arr[0],*p就是arr[0],不是整个数组 -
int** pp = &p;→pp是指针变量,*pp是p(即一个int*),**pp才是*p(即int值)
越往深层走,* 的层数越多,但每一层都只解一层地址。真正容易被忽略的,是程序员常默认“p 有值所以 *p 就安全”,却忘了检查它是否真指向合法内存。


















