2. 指针与变量:指针指向基本数据类型、指针的赋值与修改、空指针与野指针
指针这东西,说白了就是变量的「门牌号」。你想想看,变量本身住在内存里,有自己的一亩三分地。指针不存数据,它存的是「数据住在哪儿」这个地址信息。我当年刚学C语言时,总觉得指针神神秘秘的,后来发现——嗯,它就是地址的搬运工。
2.1 指针指向基本数据类型
基本数据类型,比如 int、char、float、double,它们都在内存里占一块空间。指针就是指向这块空间的起始地址。
举个例子:
int a = 42;
int *p = &a; // p 指向 a 的地址
这里 p 是个指针变量,它存的是 a 的地址。通过 *p 就能拿到 a 的值——42。我在项目中遇到过不少新手,把 p 和 *p 搞混,调试半天才发现问题。
核心理解:
p是地址(门牌号)*p是地址里存的值(屋里的人)&a是取变量 a 的地址
不同类型的指针,指向不同类型的数据。int * 只能指向 int 变量,char * 只能指向 char 变量。为什么?因为指针知道它指向的数据占几个字节。int 占4字节,char 占1字节,指针做加减运算时,步长不一样。
| 指针类型 | 指向的数据类型 | 步长(字节) |
|---|---|---|
| int * | int | 4 |
| char * | char | 1 |
| float * | float | 4 |
| double * | double | 8 |
2.2 指针的赋值与修改
指针的赋值,说白了就是让指针指向一个新的地址。你可以让指针指向另一个变量,也可以让它指向 NULL。
int x = 10, y = 20;
int *ptr;
ptr = &x; // ptr 指向 x
printf("%d\n", *ptr); // 输出 10
ptr = &y; // ptr 改为指向 y
printf("%d\n", *ptr); // 输出 20
看到了吗?指针本身是可以被重新赋值的。它今天指向 x,明天可以指向 y。我个人习惯在指针赋值时,先确认目标地址是否有效。有一次我在项目中调试一个通信协议,就是因为指针指向了错误的地址,导致数据全部错位——排查了整整一个下午。
我的小技巧:
给指针赋值时,养成先初始化的习惯。比如:int *p = NULL; 然后再赋有效地址。这样万一忘了赋值,至少不会乱指。
还有一种情况,指针指向数组元素:
int arr[3] = {1, 2, 3};
int *p = arr; // 指向数组首元素,等价于 &arr[0]
p++; // 指向 arr[1]
*p = 100; // 把 arr[1] 改成 100
指针的加减运算,实际上是在地址上跳步。跳多少?看指针类型。int * 跳4字节,char * 跳1字节。这个特性在遍历数组时特别好用。
2.3 空指针与野指针
这两个概念,我建议你刻在脑子里。空指针和野指针,是C语言里最常见的坑,没有之一。
空指针
空指针就是指向地址0的指针。在C语言里,用 NULL 宏表示。空指针的意思是:「这个指针当前不指向任何有效对象」。
int *p = NULL;
// 使用前必须检查
if (p != NULL) {
*p = 100; // 安全
} else {
printf("指针为空,不能使用\n");
}
我曾经在一个嵌入式项目中,因为没检查空指针,直接解引用,导致系统跑飞。从那以后,我养成了「用指针前先判空」的习惯。说白了,这就是个保命操作。
警告:
对空指针解引用(即 *p 操作)会导致程序崩溃。在嵌入式系统中,可能直接触发硬件异常。务必在使用前判空。
野指针
野指针更可怕。它指向一个随机的、无效的地址。野指针不是 NULL,它有一个值,但这个值是垃圾值。你根本不知道它指向哪里。
野指针的常见来源:
- 指针未初始化
- 指针指向已释放的内存(悬空指针)
- 指针越界访问
int *p; // 未初始化,野指针
*p = 10; // 危险!不知道写到哪里去了
int *q = malloc(sizeof(int));
free(q);
*q = 20; // 危险!q 指向的内存已释放
我记得有一次,团队里一个同事在代码里忘了初始化指针,结果程序运行时好时坏。查了两天,最后发现是野指针在作怪。你想想看,野指针指向的地址可能是随机的,今天运气好没出事,明天换个环境就崩了。
避坑指南:
- 指针声明时立即初始化:
int *p = NULL; - 释放内存后,立即将指针置 NULL:
free(p); p = NULL; - 不要返回局部变量的地址
- 使用指针前,先判空
2.4 知识体系图
下面这张图,把指针与变量的核心关系梳理了一遍。建议你多看几遍,把逻辑理清楚。
2.5 总结
指针与变量的关系,其实就三件事:指向谁、怎么改、别乱指。指向基本数据类型时,类型要匹配;赋值修改时,注意地址有效性;空指针和野指针,是必须时刻提防的敌人。
我个人习惯在写代码时,每声明一个指针,就立刻初始化。哪怕暂时不知道指向哪里,也先给个 NULL。这样后续使用前判空,就能避免大部分问题。嗯,这招我用了十几年,没出过事。
最后提醒一句:
指针不是洪水猛兽,它只是地址的载体。你把它当工具,它就是你手里的利器;你轻视它,它就会给你挖坑。多写、多练、多排查,慢慢就熟了。
公众号:蓝海资料掘金营,微信deep3321