声明:学习过程中的笔记,不足之处请指教
两者的含义
指针数组:int* arr[10]; 用来存放指针的数组。
解释: arr 先与“[ ]”结合,构成一个数组的定义,数组名为 arr。
如果搞不清楚运算符的优先级,那么就加上小括号(),比如定义一个指针数组,可以写成
char *(arr[10]), 这里我们要的是一个数组,所以把arr[10]括起来。
这个数组里面有10个元素,10个元素都是指针类型
数组指针:int (*p)[10]; 用来存放数组的地址。
解释:p 先和 * 结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
这里我们要的是一个指针,所以把 *arr 括起来。
p指向一个数组,该数组有10个元素,每个元素是 int型。
注意:p的类型是:int (*)[10];
p是指向一整个数组的,数组有10个元素,int [10];
p+1 会跳过10个元素,所以在数组遍历的时候要注意,例如:
int arr[10];
int (*p)[] = &arr;/*
&arr --> int(*)[10]
arr --> int*
*/
//所以 &arr + 1 也是跳过整个数组,但是arr + 1 是指向下一个元素
指针数组应用
指针数组有什么用呢?
既然指针数组是用来存放指针的数组,那么最能想到的用法,就是将一些变量的地址存放进一个数组里面。
在给定一个数组里面,我们除了可以使用下标法去遍历里面的成员之外,还可以利用地址下标找。
例子1: 对于单个一维数组
#include <stdio.h>const int MAX = 3;int main ()
{int var[] = {10, 100, 200};int i, *ptr[MAX];for ( i = 0; i < MAX; i++){ptr[i] = &var[i]; /* 赋值为整数的地址 */}for ( i = 0; i < MAX; i++){printf("Value of var[%d] = %d\n", i, *ptr[i] );}return 0;
}
例子2:对于多个一维数组
#include <stdio.h>
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 6,7,8,9,10 };int arr3[] = { 11,12,13,14,15 };int* parr[3] = {arr1,arr2,arr3};//这样就和二维数组一个意思了for (int i = 0; i < 3; i++){for (int j = 0; j < 5; j++) {printf("%3d",(*parr[i] + j));// j 指向一维数组的元素的下标//printf("%3d", parr[i][j]);// *(p+i) --> p[i]}printf("\n");}return 0;
}
例子2的解释图:
通过三个数组名,可以分别找到该数组名对应的首元素地址。(比如通过数组名arr1,找到arr1数组首元素1的地址)
强调:
数组名通常表示的都是数组首元素的地址
但是有2个例外:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
2. &数组名,这里的数组名表示的依然是整个数组,所以&数组名取出的是整个数组的地址
数组指针应用
例子1:
int main()
{ int arr[] = {1,2,3,4,5};/*指针数组int* p = arr;for (int i = 0; i < 5; i++){printf("%d ",*(p+i));}*//*数组指针对于简单的例子不推荐这个写法int (*p)[5] = &arr; //将数组arr的地址赋值给数组指针变量pfor(int i=0;i<5;i++){//printf("%d ",(*p)[i]);printf("%d ",*(*p+i));//p指向数组arr, *p相当于数组名,} 数组名又是首元素地址,所以*p本质是数组首元素地址*/return 0;
}
解释:
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
我们知道,pa
是数组指针,指向arr数组,里面存的是数组arr的地址。
既然拥有了数组arr的地址,解引用就可以拿到这个数组。(就相当于拿到了一个数组的数组名)即:
*pa //数组的地址解引用,就拿到了这个数组
拿到了数组名*pa
,要去找数组内每个元素,就可以按照正常数组元素的访问来拿到每个元素。即:
(*pa)[0]; //数组的第一个元素
因为 *pa
就等于找到了这个数组(*pa==arr)。
arr是数组名,数组名是首元素地址。
arr + i
就是从arr数组首元素的位置向后移动i
,指向下标为i的元素。
再次解引用,就是第i个元素了。即:
*(*pa+i)
例子2:
void print1(int arr[3][5], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", arr[i][j]);}printf("\n");}
}//常规写法void print2(int (*p)[5], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){//printf("%d ", *(*(p + i) + j));//*(p + i)表示行printf("%d ", p[i][j]);//等价于上面的写法}printf("\n");}
}//数组指针写法int main()
{int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };print1(arr, 3, 5);print2(arr, 3, 5);return 0;
}
小结:
引入数组指针后,我们就有两种方案来访问数组元素了,一种是使用下标,另外一种是使用指针。
1) 使用下标
也就是采用 arr[i] 的形式访问数组元素。如果 p 是指向数组 arr 的指针,那么也可以使用 p[i] 来访问数组元素,它等价于 arr[i]。
2) 使用指针
也就是使用 *(p+i) 的形式访问数组元素。另外数组名本身也是指针,也可以使用 *(arr+i) 来访问数组元素,它等价于 *(p+i)。