指针为什么总是卡人?——从野指针到指针数组的血泪史

如果你问学 C 的人,哪一块最难啃?十个里面有九个会告诉你:指针

它就像一只看不见摸不着的猫,稍不注意就抓你一爪子。初学者的常见体验是:写出来的代码不是报错,就是跑飞。更离谱的是:有时候根本没报错,结果却完全不对。

我当年学单片机的时候,第一次接触指针,几乎整整一个星期都卡在这里。今天,就带大家走一遍从“野指针”到“指针数组”的血泪史。


1. 野指针:最常见的坑

所谓野指针,就是指向了不确定内存区域的指针。比如:

#include <stdio.h>

int main() {
    int *p;  // 声明了指针,但没初始化
    *p = 10; // 写入数据
    printf("%d\n", *p);
    return 0;
}

这段代码看似没问题,编译器也不会报错,但运行起来可能直接段错误(Segmentation Fault)。因为 p 没有指向合法内存。

生活类比:这就像拿到一把钥匙,但你不知道它能开哪扇门,结果乱开,直接触发了警报。

解决方法:要么指向合法的变量,要么先分配内存。

int a = 0;
int *p = &a; // 指向合法地址
*p = 10;
printf("%d\n", *p);

2. 指针和数组:永远绕不开的孪生兄弟

初学者常常迷惑:数组和指针到底是什么关系?

int arr[3] = {1, 2, 3};
int *p = arr;

printf("%d\n", *(p+1)); // 输出 2

数组名在大多数情况下,会被当作指向首元素的指针。所以 arr 就等价于 &arr[0]。

但要注意:数组名本身不是变量,不能被重新赋值,而指针是可以改来改去的。

血泪案例

int arr[3] = {1, 2, 3};
arr = arr + 1; // ❌ 这行编译直接报错

这就是典型的“数组不是指针”的坑。


3. 指针传参:值传递 vs 引用传递

函数参数如果用指针,可以实现“改变外部变量”的效果:

#include <stdio.h>

void change(int *p) {
    *p = 100; // 修改指向的变量
}

int main() {
    int a = 10;
    change(&a);
    printf("%d\n", a); // 输出 100
    return 0;
}

如果你忘了传地址:

change(a); // ❌ 编译报错,或者类型不匹配

那就凉凉了。

类比:你想把钥匙交给朋友,让他去你家帮忙换灯泡。如果你只是告诉他“我家在北京”,不给钥匙(地址),他怎么可能进得去?


4. 内存越界:最隐蔽的炸弹

这是初学者最难排查的错误:访问数组边界以外的空间。

int arr[3] = {1, 2, 3};
printf("%d\n", arr[5]); // ❌ 未定义行为

C 语言不会帮你检查越界,你打印出来可能是乱七八糟的数字,也可能直接崩溃。

类比:这就像你家有三个房间,你却硬闯第 5 个,结果进去的是别人家,直接被赶出来。


5. 指针数组:高级但实用的工具

当你搞懂了指针和数组后,就能看懂这种“恐怖写法”:

#include <stdio.h>

int main() {
    char *strs[] = {"C语言", "单片机", "指针"};
    for(int i=0; i<3; i++) {
        printf("%s\n", strs[i]);
    }
    return 0;
}

strs 是一个数组,里面的每个元素都是一个 char*(字符串指针)。

它非常常见,比如在菜单系统、字符串表里都要用。

类比:这就像一个电话本,每一页写的不是电话号码本身,而是一个“联系人”,你要再通过联系人去拨号。


如何才能不怕指针?

  1. 先学会“地址”的概念,理解 & 和 *。

  2. 多画图,把变量、地址、指针画出来,心里才不乱。

  3. 不要害怕报错,报错是成长的一部分。

  4. 从野指针到指针数组,这是必经之路。

很多人说“指针是 C 语言的灵魂”,其实更准确的是:指针是你和底层硬件对话的钥匙。只要你能用好它,你写单片机、操作系统、驱动,都会事半功倍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_41821147

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值