C语言——指针与一维数组的关联

目录

1.数组名的理解​编辑

1.1小总结

2.使用指针访问数组​编辑

2.1小总结

3.一维数组传参的本质​编辑

3.1小总结

4.冒泡排序​编辑

4.1核心思想:相邻的元素两两比较大小。

5.二级指针​编辑

5.1图解

6.指针数组​编辑

6.1图解

7.指针数组模拟二维数组​编辑

7.1图解


1.数组名的理解

之前我们在用指针访问数组内容时有这样的代码:

int arr[] = { 0,1,2,3,4,5,6,7 };
int *p=&arr[0];

这里我们使用&arr[0]的方式,拿到数组第一个元素的地址,但实际上数组名本就是地址,而且是数组首元素的地址

不如我们那一段代码验证一下,

从打印结果可以看出来数组名就是数组首元素(第一个元素)的地址

这有人就会存有疑惑?如果数组名是数组首元素的地址。

那下面这段代码怎么理解?

输出结果如下:

可以看出来如果arr是数组首元素的地址,输出结果应该是4/8才对,但为什么输出32呢?

其实数组名就是数组首元素(第一个元素)的地址是对的,但有两个例外

sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。

&数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)。

除此之外,任何地方使用数组名,数组名都表示数组首元素的地址。

在试一试下面这段代码吧,

输出结果如下:

这里的&arr含义是数组的地址,&arr[0]含义是数组首元素的地址

这时有人疑惑,arr和&arr的地址怎么是一样的?它们有区别吗?

别急看看下面的代码吧,

输出结果:

我们发现&arr[0]和&arr[0]+1相差4个字节,arr与arr+1相差4个字节,是因为&arr[0]和arr都是首元素的地址,+1就是跳过一个整型元素,(指针类型为int*)

&arr与&arr+1相差40个字节,是因为&arr是数组的地址,+1操作是跳过整个数组

1.1小总结

1.数组名是数组首元素的地址,但有两个例外。

2.数组在内存中是连续存放的,

3.指针的+-整数运算,方便我们获得每一个元素的地址。


2.使用指针访问数组

有了前面的知识支持,在结合数组的特点,我们可以很方便的使用指针访问数组,

输出结果:

对于这段代码我们可以进一步的分析,数组名arr是数组首元素的地址,可以赋值给p,p与数组名arr是等价的,这里我们可以用arr[i]访问数组元素,那么可以用p[i]访问数组元素吗?

话不多说看代码,

输出结果:

这里将*(p+i)换成p[i]也是能正常打印的,所以实质上p[i]等价于*(p+i)

同理arr[i]也等价于*(arr+i),数组元素的访问在编译器处理的时候,也是转换成数组首元素的地址+偏移量求出元素的地址,然后再解引用来访问的。

这里 arr[i]==*(arr+i)==*(i+arr)

2.1小总结

1.数组就是数组,是一块连续的空间(数组的大小和数组元素的个数和元素类型都有关系)

2.指针(变量)就是指针(变量),是变量大小就是4/8个字节。

3.数组名是数组首元素的地址,是地址。

4.可以使用指针访问数组。


3.一维数组传参的本质

首先从一个问题开始,我们之前都是在函数外部计算数组元素个数的,那我们可以把数组传给函数后,函数内部计算数组元素个数吗?

测试代码:

输出结果:

我们发现在函数内部是没有正确获得数组元素个数,

这就要学习数组传参的本质了,我们知道数组名是首元素的地址,那么在传参的时候,传的是数组名,数组名作为参数传给函数,也就是说本质上数组传参传递的是首元素的地址。那么函数形参部分应该采用指针变量来接收首元素的地址,那么在函数内部 sizeof(arr)计算的是首元素地址的大小,而不是数组的大小。

正是因为函数参数部分的本质是指针,所以在函数内部是没有办法求出数组元素个数的

实例代码:

输出结果:

3.1小总结

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

2.数组传参的本质是传递了数组首元素的地址,所以形参访问的数组和实参的数组是同一个数组。

3.形参的数组是不会单独再创建数组空间的,所以形参的数组是可以忽略数组大小的。


4.冒泡排序

4.1核心思想:相邻的元素两两比较大小。

冒泡排序
思想:相邻元素两两比较,满足某种条件后交换

例如
将数组
10 9 8 7 6 5 4 3 2 1 进行排序(升序)
 9 10 8 7 6 5 4 3 2 1 
 9 8 10 7 6 5 4 3 2 1 
 9 8 7 10 6 5 4 3 2 1 
 9 8 7 6 10 5 4 3 2 1 
……
 9 8 7 6 5 4 3 2 1 10
这是(第一趟)第一个数字比较的过程,一共要比较9对数字,
同理可知
10 个数字要进行 9趟冒泡排序;
(n 个数字要进行 n-1趟冒泡排序)
比较数字的对数为9 8 7 ……1

输出结果:


5.二级指针

指针变量也是变量,是变量就有地址,那么指针变量的地址存放在二级指针里。

二级指针存放的是一级指针的地址,指向的是一级指针。

形式为:

int * *pp=&p;

这里的int*表示pp指向的对象p的类型是int* ,第二颗*表示pp是指针变量,

5.1图解

代码如下:

二级指针的运算

*pp其实访问的是p;那么**p的含义是先通过*p找到p,然后在对p进行解引用操作:*p那找到的就是a。


6.指针数组

思考一下,指针数组是指针还是数组?

类比 整型数组是存放整型的数组

字符数组是存放字符的数组

那么指针数组就是存放指针的数组。

形式为

存放指针的类型 +变量名+[ 数组内元素个数 ]

6.1图解

例如:int *p[3]={arr1,arr2,arr3};

指针数组内的每个元素都是用来存放指针的。

如下图:

指针数组的元素是地址,又可以指向一块区域。


7.指针数组模拟二维数组

输出结果:

分析:数组名是首元素的地址,类型是int*的,就可以存放在p数组中。

7.1图解

可以类比如图所示:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值