指针和地址是同一事物的两种说法:地址是内存字节的编号,指针是存放该编号的变量;指针变量占8字节,解引用(*)访问目标数据,未初始化的指针为野指针,危险。

指针和地址不是两个要区分的概念,而是同一事物的两种说法——地址是内存中字节的编号,指针就是存放这个编号的变量。
地址是内存的“门牌号”
内存像一栋大楼,每个字节是一个房间,地址就是房间号(比如 0x7ffd3c4)。它唯一、连续、以十六进制表示。变量被创建时,系统自动分配一块连续字节,并把起始地址作为该变量的地址。用 & 运算符就能拿到这个编号,例如:
int a = 100;
printf("%p", &a); —— 输出的就是 a 所在“房间”的门牌号。
指针是专门存地址的变量
既然地址是个数值,自然可以存到变量里。这种变量就叫指针变量,声明方式是在类型后加 *,比如 int *p; 表示“p 是一个指向 int 的指针”。它不存数据本身,只存数据的地址。
初始化必须明确指向谁:
int a = 5;
int *p = &a; —— 此时 p 的值就是 a 的地址。
注意:所有指针变量在 64 位系统中都占 8 字节,和它指向的是 int 还是 char 无关。
解引用才是访问数据的关键动作
光有地址没用,得靠解引用(*)才能读写目标数据。
*p 不是指针 p 自己的值,而是“p 所存地址处的那个值”。所以:
– *p = 20; 把 a 改成 20;
– int b = *p; 把 a 的值赋给 b。
反过来,&p 是指针变量 p 自己的地址——它也是一个地址,可以被另一个指针(比如 int **q = &p;)保存。
不初始化的指针很危险
声明但未赋值的指针(如 int *p;)内容是随机的,指向不可控内存,称为野指针。一旦解引用(*p = 1;),程序极可能崩溃。养成习惯:
– 声明即初始化,哪怕初始化为 NULL;
– 使用前检查是否为 NULL 或已有效指向;
– 指向的变量销毁后(如局部变量退出作用域),指针要及时置 NULL,避免悬垂。

















