今天我们来聊聊C语言里的指针高阶。
如果说普通指针是“外卖小哥”,那今天要讲的这些东西就是“外卖站站长”、“区域经理”甚至“总部CEO”。是不是听着就有点晕?别怕,我当年也是被int (*p)[10]和int *p[10]折磨得死去活来。今天咱们就把这些“天书”拆解成大白话,保证你看完直拍大腿:原来就这?
一、数组名:别被它骗了,它其实是个“地址精分患者”
大家一直以为数组名就是首元素地址?对,也不全对。
数组名这货很狡猾,它在不同场合穿不同的马甲。
1. 平时装老实:就是个地址

这俩输出一模一样,这时候arr就是个单纯的“门牌号”。
2. 遇到sizeof:瞬间膨胀成“整个小区”

如果arr只是个地址,在32位系统下应该是4个字节,为啥输出40?
真相是:sizeof(数组名)时,数组名不再代表首元素地址,而是代表整个数组。40就是10个int的大小。
3. 遇到取地址符&:变成了“整个小区的地址”

数值看着一样,但脾气不一样!
-
arr + 1:跳过一个元素(4个字节),变成0x0012FF34。 -
&arr + 1:跳过整个数组(40个字节),直接跳到0x0012FF58。
总结:arr是“第一户的地址”,&arr是“整个楼的地址”。虽然起点一样,但走一步的距离天差地别。
二、一维数组传参:你以为是“快递包裹”,其实是“取件码”
很多新手会犯这个错:在main里算数组长度是10,传到函数里就变成1了。

为啥?
因为你传给函数的根本不是整个数组,而是首元素的地址!
函数里的int arr[]其实编译器根本不把它当数组,它悄悄换成了int *arr。
所以sizeof(arr)算的是指针的大小(4或8),不是数组的大小。
结论:数组传参,形参要么写成int arr[](假装是数组),要么写成int *arr(老老实实写指针),反正本质都是指针。
三、二级指针:套娃开始!俄罗斯套娃
一级指针存变量的地址。
二级指针存指针的地址。

这就好比:
-
a是住在房子里的人。 -
p1是房子的钥匙。 -
p2是装钥匙的保险箱密码。
怎么取值?
-
*p1:拿到人(10)。 -
*p2:拿到钥匙(p1的值,也就是a的地址)。 -
**p2:用密码打开保险箱拿出钥匙,再开门见到人(10)。
四、指针数组 vs 数组指针:谁才是真大佬?
这两个长得像双胞胎,最容易搞混。教你一招制敌:看优先级!
1. 指针数组 (int *arr[])
核心是“数组”。

因为[]优先级高,所以arr先和[]结合,说明这是个数组。
数组里装的是什么?装的是int*类型的指针。
用途:像个“快递柜”,每个格子放一个地址。

2. 数组指针 (int (*p)[10])
核心是“指针”。

因为有了括号,p先和*结合,说明这是个指针。
这指针指向哪里?指向一个有10个元素的整型数组。
用途:专门用来指路大型数组,特别是二维数组的救星!
五、二维数组传参:终于不用再迷路了
以前传二维数组,我们用双重循环。现在有了数组指针,可以直接把整个二维数组打包带走!

这里的p就像一张导航地图,告诉你从第0行跳到第1行需要跨过多少个字节。
六、函数指针:拿着遥控器的男人
函数也有地址!函数名就是地址。
我们可以定义一个指针,专门存函数的地址,然后用这个指针来调用函数。

意义:以后我们可以把函数像变量一样传来传去,回调函数就是这么来的!
七、指针习题:来,咱们做几道“送命题”
光说不练假把式,来看看文档里的这几道题,全是面试高频坑!
题1:逗号表达式挖坑

答案:1
解析:大坑!{}里是圆括号(),不是花括号。圆括号里是逗号表达式,只取最后一个值。所以数组实际初始化是 {1, 3, 5},后面补0。所以p[0]是1。
题2:&数组名+1

答案:2, 5
解析:&a+1跳过了整个数组,指向数组末尾的后面。ptr-1往回退一格,刚好指向a[4](也就是5)。
题3:指针数组的指针

答案:at
解析:a是指针数组,存了三个字符串的首地址。pa是二级指针,指向a[0]。pa++往后跳一个单位,指向a[1],解引用出来就是"at"。
总结时间到啦!!!
|
概念 |
通俗解释 |
写法 |
|---|---|---|
|
数组名 |
平时是门牌号,sizeof时是整栋楼 |
|
|
数组传参 |
永远传的是地址,别指望在函数里算长度 |
|
|
二级指针 |
存钥匙的保险箱 |
|
|
指针数组 |
装地址的盒子 |
|
|
数组指针 |
指路的导航 |
|
|
函数指针 |
遥控器的信号 |
|
指针学到这就算是通关了!以后再看到复杂的声明,就从变量名开始,先找括号,再看右边,最后看左边。多练几次,你会发现:指针,也不过如此嘛!

385

被折叠的 条评论
为什么被折叠?



