c语言返回指针数组_c语言入门 第十五章 指针与数组

之前介绍了指针是什么,以及简单的指针的使用,接下来我们就来研究一下指针的一个重要应用:使用指针来操作数组

1 指针和数组

首先我们来观察数组

#include

b3f7adc430a53526aff876e9cb56222b.png

数组是一系列类型相同的数据的集合,我们可以通过数组名[索引]的方式打印出数组元素的指

那么如果我们直接打印数组变量会发生什么事情呢

#include

4650b5bf8149d3620608947f66ecf437.png

会输出一个值,那么这个值代表了什么

我们可以利用指针和取地址符来观察一下

#include

b42c4680930f82215f64e3f4c6d1c2d4.png

我们可以发现数组名和指向数组的指针,以及数组第一个元素的地址他们的值是相同的

3dd7985c36f1ada94d385607933bbbec.png

也就是说,数组名可以代表数组的地址,数组的地址和首元素的地址是相同的,我们定义一个指针指向数组,和定义一个指针指向数组的首元素是一样的

同时我们也了解指针的运算,那么如果把指针加1,就相当于移动了一个int长度,这时指针刚好指向了数组的第二个元素

faaf440074f79fc2a6d04e4149ca4013.png
#include

a534a53bc2877b61cd8d54d6034c5c2a.png

在这里a[1]代表数组的第二个元素,p+1,指向了第二个元素的地址,所以 s[1]==*(p+1)

这里需要注意的时取值运算符*的优先级大于+运算符,所以要加括号,否则计算的就是(*p)+1得到的结果就是第一个元素的值加1了

那么我们可以推导出来一个公式:

假设a是数组,n是元素索引,p是指向数组的指针那么数组的第n个元素使用指针来表示就是*(p+n),也就是说 a[n]和*(p+n)是等价的

如果需要遍历数组的元素,那么使用数组的索引和使用指针都可以完成

#include

d5b19dad05191733d6a128c6c238293a.png

2 指针和二维数组

我们在理解二维数组的时候通常会把二维数组理解为有行列的表格

int a[2][3]={1,2,3,4,5,6}可以理解为

efb9e4752215bb3a7e1751cf511d6fa6.png

但是实际上的储存形式是线性连续的

1e286985e40baea62c0405ef8e78e83a.png

那么如果需要获取第二行的元素a[1][0]就需要我们移动3次

9082d951c12bba00248537a597be3adb.png
#include

58c0690646a5b079ec7426feaace3332.png

这显然不是很方便

对于二维数组,如果需要去找到里面的元素,那么就需要一个能够一次跳过整行长度的指针来遍历数据

510ac9a8c899c25c2ce2b6dbc32dee3f.png

,我们需要修改一下指针的类型,把p的类型声明为 int (*p)[3]

这个声明语句比较复杂,需要仔细说明一下

在c语言的声明语句当中,需要把握住一个就近的原则,之后我们会看到各种非常复杂的类型声明,只要把握住这个原则就不会出现错误了

  • 首先需要找到声明的变量
  • 其次找到和变量结合性最高的运算符,这个时候定义的类型就是变量的类型
  • 然后根据优先级依次判断

aec43b33fd4a563a69bd6020e26cd4ed.png

首先找到变量 p ,其次由于小括号的存在*的结合性最高,所以p是一个指针,然后是[],说明这个指针指向了一个数组,最后是 int ,说明数组类型是int类型

总结出来就是 p 是一个指向整数类型数组的指针

再看声明 int * p[3] 和刚才的表达式只差一个小括号,那么声明出来的类型就完全不同

20fc308c0e88e59e7187845f18587231.png

这里[]的优先级高于*,所以 p 是数组,然后找到 * , 说明这是一个保存指针数据的数组,最后确定保存的指针是int型的

总结出来就是一个保存 int指针的数组

那么知道我们的指针是什么意思以后,就可以直接找到二维数组的指定的行

#include

3ae31fb12d42a01a8c5ec5ff8b52cb4b.png

这里的a[1]是二维数组当中的一行,我们依然可以把他看作一个数组,a[1]是数组名代表的是第二行的地址,这和我们移动一次指针的效果是一样的

接下来就需要取出a[1]这个数组当中的元素值了

#include

我们发现并没有成功

1bee0f24a407df0a63f09a122969294d.png

这是因为 p 是一个指向数组的指针,取值之后得到的是一个数组,也就是说*p是一个数组,直接打印数组得到的还是一个数组地址,所以需要取两次值

#include

6ca418d8962a6c07f06d193b6ae939e4.png

那么如果我要取出a[1]的第二个值,就可以把第一次取出来的值当做数组就可以了

#include

c537fbd02381dd9459f4f9b552befa0e.png

其实我们依然可以完全通过指针移动来实现

#include

0462bb87278cff10d9a35d80cc5ef340.png

这里的 *(*(p+1)+1) 是一个比较复杂的表达式,我们需要仔细看一下

  • p是指针,*p是指针取出的值,是一个 int 类型的数组 也就是说 *p 和 a[0] 是一致的;
  • *(p+1) 也是一个 int 类型的数组, *(p+1) 和 a[1] 是一致的
  • *(p+1)+1,表示把 数组的指针移动一位 , *(p+1)+1 相当于把 指向a[1]的指针移动一位,这个时候 *(p+1) 的类型不再是指向数组,而是指向数组的元素
  • 取值 *(*(p+1)+1) 就是指针指向的元素的值

关注点要放在当前表达式的数据类型是什么,是指向元素,还是指向数组

p和p+1 类型相同是指向数组的指针

*p和*(p+1) 类型相同是指向元素的指针

**(p)和**(p+1)以及*(*(p+1)+1)类型相同是取出的数值

可以通过*的数量来确定类型,没有*就是数组指针,一个*就是元素指针,两个*就是值

因此我们在取二维数组值的时候可以有一个公式

这 a 是二维数组,p是数组指针,m是行号,n是列号

a[m][n]就相当于 *(*(p+m)+n)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值