在之前的学习中,我们已经简单了解过了数组指针和指针数组(数组指针,指针数组,二级指针)我们知道指针数组其实就一个用来存放指针的数组.这里先做一个指针数组简单的回顾.
int* arr[10]; //这是一个存放整型指针的数组
char* arr[10]; //存放字符型指针的数组
char** arr[5]; //存放二级字符型指针的数组
而容易与之混淆的就是数组指针.
数组指针其实就是指针,这个指针指向数组.看下面的代码:
int* p1[10];
int (p2)[10];
上面两行代码分别表示什么意思?哪个是数组指针?
看到代码我们可以这样去分析,首先看第一个,找到*看右边p1与[10]结合即p1是一个数组名,也就表示一个数组,在看左边int,这说明int* p1[10]是一个数组,数组中的10个元素类型为int*(即指针数组).
第二个先找到*发现有小括号,说明p2是一个指针变量,然后看右边是[10],在看左边是int,也就说这个指针指向一个大小为10的数组,每一个元素类型又都是int型(即int (*p2)[10]是数组指针).
备注:以上的思路是为了方便判断其到底是指针还是数组,其实在代码中的表示方法是考虑到了运算符的优先级,[]的优先级要高于*,所以必须加上()来保证p先和*结合来表示一个指针变量.
关于指针数组和数组指针的应用
在学习其应用之前,先来看这样一个概念(& + 数组名 和 数组名)
其实这样一个概念之前也简单提过,这样的一个概念区分请对于指针的理解是十分必要的!
int arr[10];
毫无疑问,arr我们知道是数组名,并且数组名可以表示数组首元素的地址!
那么&arr呢?先来看这样一段代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[10] = { 0 };
printf("%p\n",&arr[0]);
printf("%p\n",arr);
printf("%p\n",&arr);
system("pause");
return 0;
}
运行结果如下:
从这个结果来看,&arr与arr好像没什么不同,似乎都是数组首元素的地址.不要着急再来看下面这样的代码:
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[10] = { 0 };
printf("arr[0] = %p\n",&arr[0]);
printf("arr = %p\n",arr);
printf("&arr = %p\n",&arr);
printf("arr + 1 = %p\n",arr + 1);
printf("&arr + 1 = %p\n",&arr + 1);
system("pause");
return 0;
}
结果如下图所示:
从这段代码中,我们足以看出&arr与arr的不同,尽管&arr与arr的值相同,都是元素首元素的地址,但它们的意义完全不同.
我们可以这样理解,&arr其实表示的是数组的地址,我们可以看到&arr + 1与arr差了16进制的28,也就是40个字节,也就说&arr + 1跳过了整个数组(大家可以细细体会一下).反之arr + 1与arr之间差了4个字节也就说arr + 1跳过了一个元素.
由此引出数组指针的使用,这其实就联系到了上面所说的&arr表示的是数组的地址,想想我们的数组指针,就是一个指向数组的指针,那么这个指针中存放的应该就是数组的地址.
#include <stdio,h>
#include <stdlib.h>
int main(){
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int (*p)[10] = &arr; //把数组arr的地址赋给指针变量p
sysem("pasue");
return 0;
}
注意,一般情况下我们很少这么写.
关于一个数值指针的使用:
#include <stdio.h>
#include <stdlib.h>
void Print_array1(int arr[3][5], int row, int col){
int i = 0;
int j = 0;
for (i = 0; i < row; ++i){
for (j = 0; j < col; ++j){
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
void Print_array2(int (*arr)[5], int row, int col){
int i = 0;
int j = 0;
for (i = 0; i < row; ++i){
for (j = 0; j < col; ++j){
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
int main(){
int arr[3][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Print_array1(arr, 3, 5);
Print_array2(arr, 3, 5);
system("pause");
return 0;
}
数组名arr表示元素首元素地址,但是在二维数组中首元素就是二维数组的第一行,所以在调用函数Print_array1时传入的arr其实就相当于第一行的地址,也就是一个一维数组的地址,所以我们换一种传入方式,传入一个数组指针(指向一维数组的指针),也就是Print_array2中的 int (*arr)[5].可以用下面这样以个示意图来帮助理解
a -> (int*)[4]
a可以看作一个行指针,类型可以看作数组指针 (int*)[4]
a[0] -> int*
a[0][1] -> int