指针数组
指针数组:是一个数组,其中的每个元素是指针。
定义方法:int* p[10];
数组指针
数组指针:是一个指针,指向了一个数组。
定义方法:int(*p)[10];
&数组名和数组名
arr是数组名,数组名表示数组首元素地址。
int arr[10]={
0};
int(*p)[10]=&arr;
int(*p)[10]=arr;
那么&arr是什么呢?
我们先来看一段代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = {
0 };
printf("%p\n", arr);
printf("%p\n", &arr);
system("pause");
return 0;
}
结果:
可以看到,数组名和&数组名打印的地址是一样的。难道两个是一样的吗?
我们再看一段代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = {
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表示的是数组的地址,而不是数组首元素的地址。数组的地址+1,跳过整个数组的大小,所以&arr+1相对于&arr的差值是40.
数组指针的使用
在下面的代码示例中:
数组名arr表示首元素的地址。二维数组的首元素是二维数组的第一行。所以这里传递的arr相当于第一行的地址,是一个一维数组,可以用数组指针来接受。
#include <stdio.h>
#include <stdlib.h>
void print_arr1(int arr[3][4], int row, int col){
int i = 0;
for (i = 0; i < row; i++){
for (int j = 0; j < col; j++){
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void print_arr2(int (*arr)[4], int row, int col){
int i = 0;
for (i = 0; i < row; i++){
for (int j = 0; j < col; j++){
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][4] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12 };
print_arr1(arr, 3, 4);
print_arr2(arr, 3, 4);
//数组名arr表示首元素的地址
//二维数组的首元素是二维数组的第一行
//所以这里传递的arr相当于第一行的地址,是一个一维数组
//可以用数组指针来接受
system("pause");
return 0;
}
数组名会隐式转换为指针
在C语言中,数组名作为函数的参数,实质是地址的传递,将数组的首地址传给形参,形参和实参共用同一存储空间,形参的变化就是实参的变化。
如果是一个int p[5]
,p的类型就是int *
。
如果是一个int p[3][5]
,p的类型就是int(*)[5]
。
如果是一个int p[3][4][5]
,p的类型就是int( * )[4][5]
。