目录
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图解
可以类比如图所示: