1. 数组名的理解
1.1 数组名是数组首元素的地址
int arr[10] = {1,2,3,4,5,6,7,8,9,10};int *p = &arr[0];
这里我们使用 &arr[0] 的方式拿到了数组第一个元素的地址,但是其实数组名本来就是地址,而且是数组首元素的地址。如下:
1.2 sizeof(数组名)与&数组名
sizeof (数组名),sizeof 中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小, 单位是字节。
&数组名,这里取出的是整个数组的地址(整个数组的地址和数组首元素 的地址是有区别的,如 1.3 所示)
1.3 &数组名与数组名
上面代码可以看到,三个打印出的地址相同,arr 和 &arr[0] 是数组首元素的地址,他们是肯定相同。那么 &arr 与它们的区别是什么呢,看下面的代码。
这里我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,是因&arr[0]和arr都是 首元素的地址,+1就是跳过⼀个元素。
但是&arr和&arr+1相差40个字节,这就是因为&arr是数组的地址,+1操作是跳过整个数组的。其实 &arr 的类型就不是 int* 了,而是数组指针类型,即 int (*p)[5]。
2. 使用指针访问数组
知道数组首元素的特点,我们就可以使用轻易指针访问数组了。
除此之外,p 也可支持 [ ] 的使用。
3.一维数组传参的本质
我们尝试将数组传给一个函数后,在函数内部求数组的元素个数。
我们发现在函数内部是没有正确获得数组的元素个数。
数组名是数组首元素的地址;而在数组传参的时候,传递的是数组名,也就是说本质上数组传参传递的是数组首元素的地址,而不是整个函数的地址。
所以函数形参的部分理论上应该使用指针变量来接收首元素的地址。那么在函数内部我 sizeof(arr) 计算的是⼀个地址的大小(单位字节)而不是数组的大小(单位字节)。正是因为函数的参数部分是本质是指针,所以在函数内部是没办法求的数组元素个数的。
4. 二级指针
指针变量也是变量,是变量就有地址。存放指针变量(一级指针变量)地址的指针就叫二级指针,其余多级指针以此类推。
对a取地址可以得到它的一级指针 pa,再对 pa 取地址就能得到二级指针 ppa。
同理,对二级指针解一次引用就可以得到一级指针,在解一次引用就可以得到一级指针指向的对象。
5. 指针数组
5.1 概念
指针数组以后面的数组为主体,即它是一个数组,是存放指针的数组。
指针数组存放的每一个元素都是指针。所以它的每个元素又可以指向一块区域。
5.2 简单运用-指针数组模拟二维数组
a[i]是访问a数组的元素,a[i]找到的数组元素(一级指针)指向了整型一维数组,a[i][j]就是整型一维数组中的元素,即各个整型元素。
上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。