C语言之指针进阶(1),数组与指针

C语言之指针进阶(1),数组与指针

码农世界 2024-06-05 后端 85 次浏览 0个评论


目录

前言

一、数组名的理解

二、使用指针访问数组

三、一维数组传参的本质

四、二级指针

五、指针数组

六、数组指针

1.数组指针的初始化

2.数组指针的使用

七、二维数组传参的本质

总结


前言

        前篇文章主要介绍了指针的基本知识,那么本篇讲重点介绍C语言中的数组与指针的关系,内容较丰富,主要内容有使用指针访问数组、一维和二维数组传参的本质、二级指针、以及指针数组和数组指针等。干货满满,希望对大家有所帮助


一、数组名的理解

我们最开始对数组名的理解是:数组名为数组首元素地址

如:

C语言之指针进阶(1),数组与指针

如上数组名确实是数组首元素的地址,

但是任何情况下数组名都是数组首元素的地址吗?

其实不然,数组名确实是数组首元素地址,但是有两个例外:

  1. sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小, 单位是字节
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)

验证:1.sizeof(数组名)

C语言之指针进阶(1),数组与指针

如上,sizeof(数组名)确实是计算了整个数组的大小,以往我们都知道,sizeof是计算变量类型的大小的,比如放一个整形在sizeof里返回的就是4。因此把数组名单独放在sizeof里的时候,数组名表示的是整个数组

验证:&数组名

C语言之指针进阶(1),数组与指针

注意观察:&arr+1刚好跳过了整个数组,来到了数组末尾元素的后一位,因此我们可以确认:&arr取出了整个数组的地址

当然一个指针肯定只能存储一个地址,它存不了整个数组的所有地址,但它表示的却是整个数组,因为&arr得到的是一个数组指针的类型,这个在后文会详细介绍,我们只需要知道指针+-整数前进或后退的步长与它的类型有关,这个在我指针初阶文章有讲到

总结:数组名为数组首元素地址,但有两个例外


二、使用指针访问数组

前面我们已经了解,数组名为数组首元素地址,除了两个例外,并且指针加减整数可以前后跳过地址,下面我们就可以使用指针访问数组了。

如:

C语言之指针进阶(1),数组与指针

关于arr[ i ]  <==> *(arr+i) 我在主页文章指针初阶已介绍,这里不再赘述

由于指针接收数组首元素地址,所以p[i] 等价于 arr[i]:

C语言之指针进阶(1),数组与指针


三、一维数组传参的本质

首先提出一个问题,我们上文计算数组元素个数是在主函数中计算然后传给函数的,那我们能不能直接在函数中计算数组元素个数呢?反正函数也接收了数组的地址

尝试:

C语言之指针进阶(1),数组与指针

我们发现计算的结果并不一致,这是为什么呢?

其实一维数组传参时,数组名只是数组首元素的地址,这个地址是由函数的一个指针类型的形参接收的,而sizeof只计算类型大小,只有单独放数组名时才计算整个数组大小,而数组名传参时已经变为一个指针类型,一个指针类型只占4/8个字节,p为指针,p[0]得到一个整形,32平台下都为4字节,相除就为1,是计算不出元素个数的

我们将函数的形参int* p换成 arr1[] 也是一样的,形参写成数组和写成指针是等价的

总结:一维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。


四、二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

这就是 二级指针。

定义语法:类型** 变量名

C语言之指针进阶(1),数组与指针

二级指针解引用

既然二级指针存储的就是一级指针的地址,那么*二级指针就是访问一级指针存储的内容:

C语言之指针进阶(1),数组与指针

那么**二级指针呢,就是访问一级指针储存的地址指向的内容:

C语言之指针进阶(1),数组与指针

总结:二级指针用来存储一级指针变量的地址


五、指针数组

指针数组是指针还是数组呢?

我们可以简单类比一下,整形数组是数组、元素为整形,字符数组是数组、元素为字符。

那么指针数组就是一个数组,元素为指针类型

定义语法:类型* 变量名[元素个数]

C语言之指针进阶(1),数组与指针

指针数组的每一个元素都是用来储存地址的:

C语言之指针进阶(1),数组与指针

比如:

C语言之指针进阶(1),数组与指针

注意:如何理解 int* parr[ ] 呢,parr与 [ ] 结合表示一个数组,int* 表示数组的元素为整形指针类型

因此我们可以用指针数组来简单模拟一个二维数组:

C语言之指针进阶(1),数组与指针

简单解释一下:

  1. 函数参数为二级指针的原因:类比上图整形数组arr1,它的类型为 int [5],我们知道数组去掉数组名剩下的就是数组的类型,它的首元素为一个整形 int,因此过去函数接收整形数组只需要创建一级整形指针变量就行,而数组parr,它的类型为int* [3],它的首元素类型为 int*,所以函数接收一个指针数组就需要二级指针来接收
  2. parr[i][j] 等价于 *((*(parr+i))+j)
  3. 这只是模拟二维数组,它不是真正的二维数组,因为二维数组的元素地址内存中是连续存放的,而这个指针数组,虽然每个指针元素变量本身的地址是连续的,但是元素储存的地址不一定是连续的

六、数组指针

前面我们知道指针数组是数组,那么数组指针就是一个指针

那么数组指针怎么创建呢?

定义语法:类型 (*变量名) [元素个数]

我们这里必须要区分清楚:

  • int* p[10],它是一个指针数组,p与[10]结合是一个数组,int与*结合表示数组的元素类型为int*
  • int (*p)[10],它是一个数组指针,*先和p结合,表示一个指针变量,再和[10]结合表示指向的数组有10个元素,int 表示指向的数组的元素为整形

    这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

    注意:无论是什么指针,只要是指针,它的大小就是4/8字节

    1.数组指针的初始化

    数组指针是一个指针,指向的是一个数组,前面我们说过&arr表示取出数组整个元素的地址,因此这个值就可以用一个数组指针来接收,因此数组指针的初始化如下:

    数组指针 = &数组名

    如:

    C语言之指针进阶(1),数组与指针

    我们通过调试就可以看到,&arr的类型就是与p一样的数组指针类型,所以我们前面所说&arr+1为什么能跳过整个数组,就是因为它是一个数组指针类型,表示整个数组

    C语言之指针进阶(1),数组与指针

    2.数组指针的使用

    C语言之指针进阶(1),数组与指针

    这里稍微解释一下:

    1. 函数形参,如前面所说,&arr表示整个数组,其实我们也可以这样理解,arr是一维数组的首元素地址,对这个首地址进行&,通常没太多意义,非要解释,可以按下面理解
    2.  *(*p+i) 的意思,*p表示解引用指向这个一维数组,一维数组元素类型为 int ,因此这里+i 是跳过 i*sizeof(int) 个字节,这里跳过字节后依然是一维数组元素的地址,因此需要再使用*号解引用一次,才能访问到其指向的数据
    3. 数组指针多用于二维数组,这里用作一维数组较牵强,一般不用作一维数组的使用,只需要理解&arr表示整个数组,+1会跳过整个数组即可,下面我们来理解二维数组传参的本质就能理解我上面所说的意思

    七、二维数组传参的本质

    我们用二维数组演示:

    C语言之指针进阶(1),数组与指针

    这里我们就能很好的理解了:

    1. 我们知道数组指针可以接收一个&一维数组,也就是,假设一个一维数组ch,令数组指针=&ch,因为我们知道&ch+1是跳过整个数组,那么数组指针+1不也是跳过整个数组
    2. 如上图,我们给函数传了一个二维数组的数组名,注意没有用&符号,只是单纯的把二维数组的数组名传给了函数,而函数是用一个数组指针的形参来接收
    3. 我们首先来理解一下二维数组,我们是不是可以把二维数组看成一个一维数组的数组,也就是说,二维数组的元素是一个个类型相同的一维数组,如上图,arr[3][5],我们可以理解为该二维数组有三个元素:arr[0]、arr[1]、arr[2]。每个元素为一个一维数组,而 [5] 表示表示一维数组有5个元素
    4. 理解了二维数组,我们再来看看二维数组的数组名,如规则所说,数组名为数组首元素地址,那么二维数组的数组名就是arr[0]的地址,也就等价于&arr[0],这样就说得通了,为什么函数要用数组指针来接收,因为二维数组的数组名就是它首元素的地址,也就是&arr[0]。
    5. 所以对于*(*(p + i) + j)的理解就是这样,*(p+i)为跳过i个一维数组,再解引用锁定这个一维数组的首元素地址,也就是p[i],找到其一维数组的首地址,再 +j 找到一维数组的元素地址,最后再*解引用找到该元素,也就是p[i][j]

    总结:⼆维数组传参,形参的部分可以写成数组,如arr[3][5],也可以写成指针形式,如 int (*p)[5]。


    总结

            以上就是本文关于数组与指针的全部内容了,偏理解,建议多看几遍,如有不通欢迎提出,一定会解答的,最后感谢大家的支持

转载请注明来自码农世界,本文标题:《C语言之指针进阶(1),数组与指针》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,85人围观)参与讨论

还没有评论,来说两句吧...

Top