c语言基础(4)——数组传参

一、指针与数组

1、[ ]操作符与数组名的理解

         我们都知道[ ] 操作符可以用来访问数组元素,那么这个是如何做到的呢?以上图中的数组arr为例,可以看出[ ] 中的数字每加1就跳过一个int大小的字节指向了下一个元素。既然数组的空间在内存中是连续的,那么根据int* 型指针+1跳过一个int指向下一个int的特性,如果用指针来表示每一个元素就是:起始地址+0、起始地址+1、起始地址+2......                                                                         那么一般的使用arr[0]、arr[1]这样的方式访问数组元素的本质也就不难理解了。其实对于一个数组,数组名arr就相当与一个被const修饰的指针变量,存放着数组首元素的地址,而对数组名使用  [ ]操作符其本质就是用指针进行访问,如:arr[3] <=> *(arr+3)。

        注意:既然arr是数组首元素地址可以用[ ]操作符,那么如果另有指针p也指向首元素地址,也可以通过p[0]、p[1]来访问数组元素。

2、数组地址

        我们已经知道了数组名arr代表数组首元素的地址,那么如何得到整个数组的地址呢?有以下两种的到整个数组地址的方法。

2.1 sizeof(数组名)

        当sizeof操作符( ) 中单独放一个数组名时,得到的是整个数组的size。

2.2 &数组名

        arr代表首元素地址,&arr就能得到整个数组的地址。他们+1跳过的字节数是不一样的。

        上图&arr+1跳过一个数组(40字节),arr+1跳过一个整型(4字节)

3、数组指针

        有指向int的指针,也有指向char型的指针,那么肯定也有数组指针了。所谓数组指针,就是指向数组的指针。对于一个二维数组,其实就是一个一维数组,数组的每个元素又是一个一维数组,那么既然数组名是数组首元素的地址的话,这个二维数组的数组名就是一个指向一维数组的指针。

<——哪一个是数组指针呢?

        pa2是数组指针,因为 [ ] 的优先级要⾼于 * 号,所以必须加上( )保证pa2与 * 号先结合,表明pa2是一个指针,留下来的 int  [10] 说明指向的数据是一个数组,数组的元素是int型的,元素个数有10个。

4、指针数组

        指针数组是指针还是数组?                                                                                                                我们类⽐⼀下,整型数组,是存放整型的数组,字符数组是存放字符的数组。那指针数组呢?是存放指针的数组。

所以指针数组就是数组元素是int*的数组。——>

5、模拟二维数组

5.1 指针数组模拟二维数组

        指针数组可以用来模拟一个二维数组,可能有人会疑惑二维数组的数组元素不是一个一维数组吗?现在指针数组的数组元素是一个指针如何能模拟呢?                                                                      我们知道,数组名其实就是首元素的地址,通过[ ]操作符对数组元素进行访问,可以说数组本质上和指针一样的。

        那么指针数组模拟的二维数组和真正的二维数组有什么区别呢?                                                      指针数组是三个连续排列的指针分别指向三个不连续的一维数组空间(下图一),而二维数组是三个一维数组在内存中连续的排列(下图二)。  

5.2 malloc模拟二维数组

        和指针数组几乎一样三个指针指向三个不连续的数组空间,不同的是,三个int*的指针不是用一维数组存储的,而是用int**的指针模拟的数组。

        

二、数组传参

1、一维数组传参的本质

        让我们先从一个问题开始,一般在函数传参时都要传数组和元素的个数,那么我们能不能在传参的时候只传数组,在函数内求元素个数呢?我们来实践一下。

        可以看到,在主函数求出的元素个数和在函数内求的不同,很明显在主函数中求出的size才是正确的。那么这是为什么呢?让我们进入调试看一看。

        原来是求整个数组的大小时出了问题,但到底为什么会的出不同的答案呢?我们之前说过,数组名就是数组首元素的地址,我们在数组传参的时候也是直接将数组名作为参数,既然是一个地址就应该用指针来作为函数的参数呀。                                                                                                     会不会函数参数中的 int arr [ ] 其实就是一个指针呢?而且如果真的是一个指针的话,求出来的大小为8也就可以解释了,在64位系统下的指针大小就是8个字节。我们将函数参数改为指针试试。

<——并没有报错。

        所以这也是用创建时的数组名访问数组元素与用一个指针来访问数组元素的区别,用sizeof和&符时只有用数组名时得到的数据是整个数组的。                                                                                      总结:数组传参本质上传的是数组首元素的地址,被调用的函数创建了一个指针变量的形参来接受这个地址,所以sizeof(arr)求的是指针变量的大小导致了元素个数算错。数组的元素个数只能在数组被创建的函数中求得。                                                                                                                注意:因为在函数中操作的是地址,所以在函数内改变数组值时,其实在函数外也改变了。

2、二维数组传参的本质

        在理解了一维数组传参的本质后,我们知道数组传参本质上传的是地址,要用对应的形参来接收地址。那么二维数组也同理。

2.1 二维数组形参

             二维数组的第二个[ ] 也就是代表列数的[ ]里面的数字不能省去,因为形参本质上是一个接收数组元素的对应的指针,而二维数组的数组元素类型就是int [5]。而第一个[ ]实际上是数组元素个数,和数组元素的类型无关,所以可以省略。

        

2.2 数组指针形参

        有了之前的理解再来看二维数组的数组指针传参就很简单了。

        

2.3 最小元素对应指针传参

        之前的二维数组的传参必须在函数形参给出固定的列数,那么如果我想用一个函数能处理不同列数的二维数组应该如何写形参呢?

        

        二维数组最小元素是一个个int型整数,其次是int[5]的一维数组。而我们知道二维数组在内存中的地址是连续的,所以我们可以直接用指针计算出第 i 行第 j 列的int整数的地址进行访问。

3、模拟二维数组传参 

3.1 数组形参

        和一维数组传参大同小异,都是一维数组,不同的是前者的数组元素是int型整数,而后者是int*的指针,指向各个数组首元素的地址。

                ​​​​​​​        

3.2 二级指针形参

                        

  • 75
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值